【问题标题】:Deleting a custom doubly linked list删除自定义双向链表
【发布时间】:2014-08-27 20:40:52
【问题描述】:

列表属性: 一个指向下一个节点的指针,另一个指向列表中任意节点的指针。

结构

struct node
{
    int val;
    node* link[2];
    node(int x);
    ~node();
};
node :: node(int x)
{
    val = x;
    link[0] = NULL;
    link[1] = NULL;
}
node :: ~node()
    {
        delete(link[0]);
        delete(link[1]);
    }

class List
{
    node *head, *cloneHead;
    node *stack[100];
    int childIndex[2][100];
    int stptr;
public:
    List();
    ~List();
    void createList(int[] , int[][2], int );
    int createListStruct(node*);
    void createCloneList();
    void clone();
    void printClone();
};

创建列表

void List::createList(int a[], int child[][2], int size)
{
    node* linkedList[size];
    for(int i=0;i<size;i++)
    {
        linkedList[i] = new node(a[i]);
    }
    head = linkedList[0];
    for(int i=0;i<size;i++)
    {
        for(int j=0;j<2;j++)
        {
            if(child[i][j]!=-1)
            {
                linkedList[i]->link[j] = linkedList[child[i][j]];
            }
        }
    }
}

主要

int main()
{
    int a[]={10,1,3,7,2,8,20};
    int child[][2] = {{1,4},{1,2},{3,-1},{6,5},{6,5},{-1,0},{5,5}};
    int size = sizeof(a)/sizeof(a[0]);
    List L;
    L.createList(a,child,size);
    L.clone();
    L.printClone();
    return 0;
}

在正常情况下,析构函数可以正常工作,但对于具有上述 List 属性的列表则失败

例如:

节点:1

Link1 : 节点 2

Link2:节点 3

节点:2

Link1:节点 3

Link2:节点 1

在上述情况下,当析构函数到达Node2的Link2时,它指向节点1,节点1已经被删除,所以代码抛出分段错误。

我想出了:在列表中有一组唯一节点并一个一个删除

还有其他方法吗?

【问题讨论】:

  • 我没有关于您构建列表的方式的所有信息。因此,我无法给出准确的答案,但是您为什么要删除第二个链接指针?似乎您正在多次释放节点。
  • 另一种情况,如果第二个链接是唯一指向特定节点的东西。
  • 是否有多个节点不是某些其他节点的下一个节点(除了第一个节点,显然不是,除非您正在考虑循环列表)。在这种情况下,shared_ptr、weak_ptr 答案对您不起作用。

标签: c++ linked-list destructor


【解决方案1】:

您可以使用 shared_ptr,它们将在最后一个指针被销毁或重新分配时释放内存。您唯一需要记住的是避免循环,这就是为什么对于任意节点 ponter 使用weak_ptr 来代替。

struct node; // forward declaration

struct node
{
    int val;
    shared_ptr<node> next;
    weak_ptr<node> other;
};

【讨论】:

    【解决方案2】:

    您的列表想法的 2 个替代方案(看起来不错)

    1. 为每个节点保留一个父节点列表。当一个节点被删除时,将所有父节点指向该节点的指针设置为nullptr。您可以随时安全地删除nullptr

    2. 如果您的图是一棵树(即没有循环),您可以使用共享指针或 unique_pointers 来使用引用计数

    【讨论】:

    • 此时父节点已经被删除,所以如果我尝试将链接设置为空,那么它将是分段错误错误。
    • 由于递归调用析构函数,当调用其子节点的析构函数时,父节点仍然(但几乎没有)活着。包含指针的内存肯定仍然被分配。
    • 我想知道有没有不使用额外空间的选项
    猜你喜欢
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多