【问题标题】:C++ How to remove node without memory loss?C ++如何在不丢失内存的情况下删除节点?
【发布时间】:2019-06-08 23:04:56
【问题描述】:

我只是无法让这个单链表在不丢失记忆的情况下工作。我已经用谷歌搜索了,据我所知,我做了最建议的事情。我也尝试过“free(deleteNode)”而不是“delete deleteNode”。有人认为他们知道答案吗?

提前谢谢你。

我正在尝试使用此代码插入和删除-p

List l{};
l.insert(5);
l.remove(5);

我敢打赌错误出在我的remove 函数中:

void List::remove(int input){

    if(top -> getValue() == input){
        Node * deleteNode = new Node;
        deleteNode = top;
        top = top -> getNext();
        delete deleteNode;
        amount--;
        return;
    }

    Node * tmpNode;
    tmpNode = new Node(top);

    while(tmpNode -> getValue() != 0){
        if(tmpNode -> getNext() -> getValue() == input){
            Node * deleteNode;
            deleteNode = new Node(tmpNode -> getNext());
            tmpNode -> setNext(deleteNode -> getNext());
            deleteNode -> setNext(nullptr);
            delete deleteNode;
            amount--;
            return;
        }
        tmpNode = tmpNode -> getNext();
    }
}

我的抄送文件:

#include <cstddef>
using namespace std;
#include "List.h"
#include <iostream>

List::List() : amount(0), top(nullptr) {
}

List::List(Node* input) : List(){
    top = input;
}

List::~List(){//destructor
    while( top != nullptr){
        remove( top -> getValue());
    }
}

List::Node::~Node(){//destructor
    next = nullptr;
    //this =NULL;
}

    List::List(List const& other) : List(){
        *this = other;
    }

    List::List(List && other) : List(){ // move constructor
       Node* tmpNode = other.top;
       other.top = top;
       top = tmpNode;
       int tmpAmount = size();
        setSize(other.size());
        other.setSize(tmpAmount);
    }

    List & List::operator=(List && other){ // move assignment
        Node* tmpNode = other.top;
        other.top = top;
        top = tmpNode;
        int tmpAmount = size();
        other.size();
        setSize(other.size());
        other.setSize(tmpAmount);
        return *this;
    }

    List & List::operator=(List const& other){// copy assignment
        Node * tmpNode; 
        tmpNode = other.top;

        while(tmpNode != nullptr){
            insert(tmpNode -> getValue());
            tmpNode = tmpNode -> getNext();
        }

        return *this;
    }

void List::setSize(int input){
    amount = input;
}

void List::insert(int input){
    Node* newNode;
    newNode = new Node(input);
    if(!top){
        top = newNode;
        amount++;
        return;
    }

    if(input > top -> getValue()){
        newNode -> setNext(top);
        top = newNode;
        amount++;
        return;
    }

    top -> putIterator(newNode);
    amount++;
    return;
}

string List::print(){
    if(top == nullptr){
        return "";
    }
    string output = to_string(top -> getValue());
    if(top -> getNext() == nullptr){
        return output;
    }
    return top -> getNext() -> print(output);
}

void List::remove(int input){

    if(top -> getValue() == input){
        Node * deleteNode = new Node;
        deleteNode = top;
        top = top -> getNext();
        delete deleteNode;
        amount--;
        return;
    }

    Node * tmpNode;
    tmpNode = new Node(top);

    while(tmpNode -> getValue() != 0){
        if(tmpNode -> getNext() -> getValue() == input){
            Node * deleteNode;
            deleteNode = new Node(tmpNode -> getNext());
            tmpNode -> setNext(deleteNode -> getNext());
            deleteNode -> setNext(nullptr);
            delete deleteNode;
            amount--;
            return;
        }
        tmpNode = tmpNode -> getNext();
    }
}

List::Node List::find(int input){
    return iterate(input).getNext();
}

List::Node List::iterate(int input){
    return top -> iterate(input);
}

bool List::isEmpty(){
    if(size()==0){
        return true;
    }
    return false;
}

int List::size(){
    return amount;
}

List::Node::Node(int input, Node &nextInput){
    value = input;
    next = &nextInput;
}

List::Node::Node(int input){
    value = input;
    next = nullptr;
}

List::Node::Node(const Node* input){
    *this = *input;
}

List::Node* List::Node::getNext(){
    return next;
}

void List::Node::setNext(Node* input){
    next = input;
}

int List::Node::getValue(){
    return value;
}

/*
void List::Node::deleteNode(){
    delete *this;
}*/

void List::Node::putIterator(Node* newNode){
    if (next == nullptr){
        next = newNode;
        next -> setNext(nullptr);
        return;
    }

    if(getValue() == newNode -> getValue()){
        newNode -> setNext(getNext());
        setNext(newNode);
        return; 
    }

    if(next -> value < newNode -> value && value > newNode -> value){
        newNode -> setNext(getNext());
        setNext(newNode);
        return;
    }

    next -> putIterator(newNode);
    return;
}

string List::Node::print(string input){
    input = input + ", " + to_string(value);
    if(next == nullptr){
        return input;
    }
    return next -> print(input);
}

List::Node List::Node::iterate(int input){
    if (next -> value==input){
        return *this;
    }
    if (next -> value==0){
        return nullptr;
    }

    return next ->iterate(input);
}

bool List::Node::operator!() const{
    if(value == 0){
        return true;
    }
    return false;
}

我的头文件:

#ifndef _LIST_H_
#define _LIST_H_
#include <string>

class List
{
  public:
    List();

    ~List(); //destructor
    List(List const &other);
    List(List &&other);                 // move constructor
    List &operator=(List &&other);      // move assignment
    List &operator=(List const &other); // copy assignment

  class Node
    {
      public:
        Node() = default;
        ~Node();
        Node(int input, Node &nextInput);
        Node(int input);
        Node(const Node *input);
        Node *getNext();
        void setNext(Node *input);
        int getValue();
        Node iterate(int input);
        void putIterator(Node *newNode);
        void deleteNode();
        bool operator!() const;
        std::string print(std::string input);

      private:
        int value;
        Node *next;
    };

    List(Node* input);
    void insert(int input);
    void remove(int input);
    Node iterate(int input);
    int size();
    bool isEmpty();
    Node find(int input);
    std::string print();
    void setSize(int input);

   private:

    Node *top;
    int amount;
};

#endif

【问题讨论】:

  • Node * deleteNode = new Node; 创建一个新节点。但是您会立即失去对该节点的引用:deleteNode = top;。结果,新创建的节点永远在内存中。应该只是Node * deleteNode = top
  • 你怎么知道自己失忆了?
  • 您无法通过在 Google 上搜索来解决此类问题。链表应首先在纸上绘制,使用方框和线条显示删除节点所需的步骤。然后你拿你在纸上画的东西,按照你在纸上画的计划写代码。如果有错误,您会看到您的程序与您的计划相违背的地方并进行更正。随机尝试的东西不会减少它。

标签: c++ linked-list nodes


【解决方案1】:

你为什么要在remove()中创建一个新节点呢?

接下来,将 getter、setter 和所有其他废话添加到 Node(这是 List 的实现细节)只会使 List 复杂化。将其全部删除(也许除了 ctor)。

考虑使用双重间接或其他方式来消除特殊情况和由此产生的容易出错的重复:

void List::remove(int x) {
    auto p = &top;
    while (*p && p[0]->value != x)
        p = &p[0]->next;
    if (*p)
        delete std::exchange(*p, p[0]->next);
}

替代方案:

void List::remove(int x) {
    auto curr = top;
    curr = nullptr;
    auto next = top;
    while (next && next->value != x) {
        curr = next;
        next = next->next;
    }
    if (!next)
        return;
    (curr ? curr->next : top) = next->next;
    delete next;
}

【讨论】:

  • 恕我直言,指向指针的指针很聪明,但处理特殊情况的方式非常混乱。它可能对树(你应该处理左右孩子)更有用,但对于列表,它会使事情变得不合理地复杂。有更简洁/更简单的方法可以消除重复。
  • 我看不出您的评论与我的评论有何关联。其实我不明白你在说什么:)
  • 使用prev 节点。与p 一起更新它。最后检查是否prev == null 并更新headprev-&gt;next。当然,它不太简洁,但是恕我直言,更容易理解。
  • @dyukha 使用两个指针并没有那么久......虽然我仍然更喜欢双重间接,但我添加了它。
【解决方案2】:

您正在调用新的构造函数,然后设置指针,这会造成内存丢失。

Node * deleteNode = new Node;

为您不想要的新节点分配内存。这是您的内存泄漏发生的地方,因为您将 设置为新地址而导致旧内存泄漏。

New的作用是分配堆内存,所以只有在你选择分配更多内存时才调用它。

非常简单的解决方案是在声明对象时不要调用 new。尝试类似:

void List::remove(int input){

    if(top -> getValue() == input){
        Node * deleteNode;
        deleteNode = top;
        top = top -> getNext();
        delete deleteNode;
        amount--;
        return;
    }

    Node * tmpNode;
    tmpNode = top;

    while(tmpNode -> getValue() != 0){
        if(tmpNode -> getNext() -> getValue() == input){
            Node * deleteNode;
            deleteNode = tmpNode -> getNext());
            tmpNode -> setNext(deleteNode -> getNext());
            deleteNode -> setNext(nullptr); // you could probably delete this line
            delete deleteNode;
            amount--;
            return;
        }
        tmpNode = tmpNode -> getNext();
    }

}

【讨论】:

    猜你喜欢
    • 2021-05-10
    • 2023-04-03
    • 2017-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多