3

我刚刚实现了链接列表。它工作得非常好,但即使很难,我也看到了我无法在 Node 上创建工作析构函数的符号,这就是为什么它没有在代码中实现。

  1. 我需要在节点上实现工作析构函数
  2. List 的析构函数,但这个很简单,我将只使用 Node 类的析构函数(但我需要这个)。
  3. 使 List 对 Node 友好,这样我就不必使用 getNext(),但我想我可以自己处理它(不知道如何,但我会找出来的)。

请看一下代码,它非常好,如果你复制它就可以了。

#include <cstdio>
#include <cmath>
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

class Node {
public:
    Node(Node* next, int wrt) {
        this->next = next;
        this->wrt = wrt;
    }

    Node(const Node& obiekt) {
        this->wrt = obiekt.wrt;
        this->next = obiekt.next;
    }
    ~Node() {}

    void show() {
        cout << this->wrt << endl;
    }

    int getWrt(){
        return this->wrt;
    }

    Node* getNext(){
        return this->next;
    }

    void setNext(Node* node){
        this->next = node;
    }

 private:
    Node* next;
    int wrt;
};

class List{
public:
    List(int wrt){
        this->root = new Node(NULL, wrt);
    }

    List(const List& obiekt){
        memcpy(&this->root,&obiekt.root,sizeof(int));
        Node* el = obiekt.root->getNext();
        Node* curr = this->root;
        Node* next;
        while(el != NULL){
            memcpy(&next,&el,sizeof(int));
            curr->setNext(next);
            curr = next;
            next = curr->getNext();
            el = el->getNext();
    /*      curr->show();
            next->show();
            el->show(); */
        }
    }

    void add(int wrt){
        Node* node = new Node(NULL, wrt);
        Node* el = this->root;
        while(el->getNext() != NULL){
            //el->show();
            el = el->getNext();
        }
        el->setNext(node);
    }

    void remove(int index){
        Node* el = this->root;
        if(index == 0){
             //deleting old one
             this->root = this->root->getNext();
        }
        else{
            int i  = 0;
            while(el != NULL && i < index - 1){
            //  el->show();
                el = el->getNext();
                i++;
            }
            if(el!=NULL){
                Node* toRem = el->getNext();
                Node* newNext = toRem->getNext();
                el->setNext(newNext);
                //deleteing old one
            }
        }
    }

    void show(){
        Node* el = this->root;
        while(el != NULL){
            el->show();
            el = el->getNext();
        }
    }

    ~List(){}

private:
    Node* root;
};

int main(){
    List* l = new List(1); //first list
    l->add(2);
    l->add(3);
    l->show();
    cout << endl;

    List* lala = new List(*l); //lala is second list created by copy cosntructor
    lala->show();
    cout << endl;

    lala->add(4);
    lala->remove(0);
    lala->show();

    return 0;
}
4

3 回答 3

3

我建议你从实现析构函数开始List。由于您通过 using 动态分配内存new,因此您应该通过 using 释放它delete。(如果您使用new[],它将是delete[]):

~List()
{
    Node* currentNode = this->root; // initialize current node to root
    while (currentNode)
    {
        Node* nextNode = currentNode->getNext();    // get next node
        delete currentNode;                         // delete current
        currentNode = nextNode;                     // set current to "old" next
    }
}

一旦你有适当的析构函数,你应该尝试你的复制构造函数是否正确:

List* lala = new List(*l);
delete l; // delete list that was used to create copy, shouldn't affect copy

你会发现你的复制构造函数是错误的,也会导致你的应用程序崩溃。为什么?因为复制构造函数的目的是创建一个对象作为现有对象的副本。您的复制构造函数只是复制假设sizeof(Node*)等于的指针sizeof(int)。它应该如下所示:

List(const List& list)
{
    // if empty list is being copied:
    if (!list.root)
    {
        this->root = NULL;
        return;
    }

    // create new root:
    this->root = new Node(NULL, list.root->getWrt());

    Node* list_currentNode = list.root;
    Node* this_currentNode = this->root;
    while (list_currentNode->getNext())
    {
        // create new successor:
        Node* newNode = new Node(NULL, list_currentNode->getNext()->getWrt());
        this_currentNode->setNext(newNode);
        this_currentNode = this_currentNode->getNext();
        list_currentNode = list_currentNode->getNext();
    }
}

您的函数remove也是错误的,因为它“删除”了对某个节点的引用,但从不释放该节点所在的内存。delete应该调用以释放此内存。

“我需要在节点上实现工作析构函数” - 不,你不需要。Node 本身不分配任何内存,因此它不应该释放任何内存。Node 不应该负责销毁Node* next或清理存储它的内存。不要实现 Node 的析构函数或复制构造函数。您还想阅读以下内容:什么是三法则?

“使列表对 Node 友好,这样我就不必使用 getNext()” - 你想在 Node 类中说,那class List就是它friend

class Node
{
    friend class List; // <-- that's it

请注意,您包含代码的这 5 个标头中只需要一个:<iostream>. 另请注意,using namespace std;在文件开头写入被认为是不好的做法,因为它可能会导致您的某些类型的名称变得模棱两可。在小范围内明智地使用它或改用std::前缀。

于 2012-05-26T21:53:56.237 回答
1

delete当与先前分配的指向链表的指针一起使用时,或者当链表变量超出范围时(例如,从函数返回时破坏局部变量),将调用链表析构函数。

链表的析构函数应该负责释放您之前为节点保留的内存(即使用add操作)。因此,基本上,您需要遍历节点列表delete并对每个节点应用操作。有一个小技巧:当你要删除一个节点时,你必须小心不要丢失指向下一个元素的指针(当一个节点被删除时,你不能确定该next成员仍然有效)。

于 2012-05-26T21:01:31.973 回答
0

如果你想为你的节点创建一个析构函数,它实际上应该很简单。

这里是:

class Node {
    private:
        int wrt;
        Node* next;
    public:
        Node(Node* next, int wrt) {
            this->next = next;
            this->wrt = wrt;
        }

        // Your desired destructor using recursion
        ~Node() {
            if ( next != NULL )
                delete next;
        }
};

就这么简单:)

基本上,在节点被删除之前,如果 next 不为空,我们删除 next,这将再次调用 next 的析构函数,如果 next->next 不为空,则再次调用析构函数。

然后最后所有节点都被删除。

递归处理了整个事情:)

于 2015-12-15T17:43:26.980 回答