链表c++的递归删除

recursive deletion of linked list c++

本文关键字:删除 递归 c++ 链表      更新时间:2023-10-16

你能告诉我为什么下一个代码的实现会导致错误吗:

void del (num*&head) {
    num*temp = 0;
    if (head!=0) {
        temp = head;
        delete temp;
        del (head->next);
    }
    else return;
}

错误:

Access violation reading location 0xcdcdcdc1.

而下一个代码工作正常:

void del (num*&head) {
    if (head!=0) {
        del (head->next);
        delete head;
    }
    else return;
}

删除temp将使head无效,因为它们都指向同一个对象。head->next试图访问已删除的对象,给出未定义的行为。您应该存储head->next,这样就不必访问已删除的对象:

if (head) {
    num * temp = head->next;
    delete head;
    del (temp);
}

您正在运行调试构建,因此删除的内存被设置为垃圾,而不是保留其旧内容。这意味着,尝试将从中读取的值用作指针将很快触发访问冲突,从而帮助您找到问题的根源。

第二个版本会等到您处理完对象后再删除它,所以没有未定义的行为。

然而,递归是个坏主意,因为如果列表太长,它可能会导致堆栈溢出。迭代会更安全:

while (head) {
    num * temp = head->next;
    delete head;
    head = temp;
}

您正在访问head->next,而实际上您已经删除了前一行的head

另一种方法是:

void del (num*&head) {
    if (head!=0) {
        num* temp = head->next;
        delete head;
        del (temp);
    }
    else return;
}

在第一个版本中,

    temp = head;
    delete temp;
    del (head->next);

temphead指向同一节点,则该节点被删除并变为无效。但它是在的最后一行访问的

    del (head->next);

第二个版本没有这个问题。

    temp = head;
    delete temp; // head is dead too!
    del (head->next); // dereferencing disposed pointer

只要您使用指向同一内存的指针进行操作,删除任何指针都会使内存被删除。因此,即使你不删除其他指针,它们也指向一块垃圾(甚至指向另一个人拥有的内存)

这样想:-

当你完成

 temp = head;// it means temp and head are talking about the same person,i.e, the same memory location.
 delete temp; //the person(memory location) to which the both of them are pointing is dead;
 del (head->next); //Now you trying to kill the "ghost" of the person means you are trying to delete already deleted node.

但在第二种情况下,递归调用刚好高于

delete head;

因此递归调用首先进行到末尾,然后从末尾开始删除节点,如下所示:-

如果您有n个节点,递归调用的摘要可以查看为:-

 del (list); // call from main.
 del (list->head); //recursive call.
 del (list->head->head);//recursive call.
 del (list->head->head->head);//recursive call.

等等…………

所以当最后一个节点出现时,其CCD_ 9是CCD_。所以这里没有像你的第一个案例那样造成伤害。