链表调试(删除C++关键字神秘)?

linked list debugging (delete C++ keyword is mysterious)?

本文关键字:关键字 C++ 调试 删除 链表      更新时间:2023-10-16

我正在尝试解决一个问题:从单向链表中删除节点,只提供指向该节点的指针。我的方法是将列表中下一个元素的数据覆盖到列表的当前元素上。

在下面的代码中,我有两个版本的删除代码:deleteNode和deleteNode2。

void deleteNode(Node * x) {
while(x->next != NULL){
x->data = x->next->data;
x = x->next;
}
delete x;
x=NULL;
}
void deleteNode2(Node * x) {
while(x->next->next != NULL){
x->data = x->next->data;
x = x->next;
}
x->data = x->next->data;
delete x->next;
x->next=NULL;
}

我用:1,2,3,4,5初始化列表并尝试删除节点3。对于 deleteNode,输出为:1,2,4,5,0,而对于 deleteNode2:1,2,4,5

同样,当我从 deleteNode2 中删除"x->next=NULL"行时,它具有与 1 相同的输出。我的问题是,删除语句在C++中如何工作?它是否将地址指向的所有位设置为 0?

对于 deleteNode(..),x 指针已被删除,但它未正确设置为 NULL,因为它打印 0 而不是跳过它。对于 deleteNode2,语句 "x->next=NULL" 等效于 deleteNode 中的 "x=NULL",因为这两个指针在概念上指向同一个地址,但它们没有相同的效果?

代码的其余部分如下所示:

#include<iostream>
#include<stdlib.h>
using namespace std;
class Node {
public:
int data;
Node * next;
Node ( int a ) { 
data = a ; 
next = NULL; 
}
};
bool appendToTail ( Node * ptr, int a ){
while (ptr->next != NULL)
ptr = ptr->next;
if (ptr==NULL) {
return false; 
}
else {
ptr->next = new Node(a);
}
}
void printList (Node * head) {
while (head!=NULL){
cout<<head->data<<endl;
head = head->next;
}
}
int main(void) {
Node * head;
head = new Node(1);
appendToTail(head,2);
appendToTail(head,3);
appendToTail(head,4);
appendToTail(head,5);
Node * i = head->next->next;
printList(head);
cout<<"removed:"<<endl;
deleteNode2(i);
printList(head);    
return 0;
}

关于为什么 x 不会改变的答案可以用一个更简单的程序来演示:

#include <iostream>
void foo(int x)
{
x = 10;  // change it to 10
}
int main()
{
int num = 4;
foo(num);
std::cout << num; // num is still 4!  Why?
}

那么为什么 num 仍然是 4? 为什么值没有更改为 10? 查找"按值传递",因为这就是您在指针代码中执行的操作。

您应该通过引用传递指针,或者通过指向指针的指针传递指针(如果您需要进一步解释,请修复上面的示例,使 num 等于 10 返回 foo 时)。

这两个函数都无效。

在第一个函数中,您省略了正确设置当前节点的数据成员next的语句。

这就是函数必须看起来像

void deleteNode( Node *x ) 
{
if ( x )
{
while ( x->next != NULL )
{
x->data = x->next->data;
Node *tmp = x->next;
x->next = x->next->next;
x = tmp;
}
delete x;
}
}

但是,如果它是列表的唯一元素,则此函数不允许删除列表的头部。

第二个函数至少具有未定义的行为x->next因为它可以等于 NULL,因此循环中的条件

while(x->next->next != NULL){

无效。