C++单链表中指针与指向指针的指针的困惑:删除偶数节点解析
单链表偶数节点删除:两段代码的核心差异解析
先看两段实现删除单链表偶数节点的代码:
第一段代码(存在断链问题)
void delete_even() { node* ptr = head; while (ptr) { if (ptr->data % 2 == 0) { node* aux = ptr; ptr = ptr->next; delete aux; } else { ptr = ptr->next; } } }
这段代码的问题很明确:它只在自己的遍历指针ptr上移动,却没有修改链表本身的链接关系。举个具体例子:
- 若链表是
1 -> 2 -> 3,删除2时,ptr先指向2,再跳到3,接着删除2,但节点1的next指针仍指向已被释放的2,后续访问链表会出现野指针或断链。 - 若头节点本身是偶数(比如
2 -> 3 -> 4),删除头节点后,全局head指针完全没被更新,依然指向已释放的节点,整个链表直接“失联”。
第二段代码(正确实现)
void delete_even() { node **p= &head; while (*p) { if ((*p)->data % 2 == 0) { node *nextptr=*p; *p=(*p)->next; delete nextptr; } else { p= &(*p)->next; } } }
这段代码用了指向指针的指针p,本质是直接操作链表中存储节点地址的“关键位置”:
- 初始时
p指向全局head指针的地址,*p就是head本身。 - 当要删除节点时,
*p = (*p)->next直接修改了这个关键位置的值:如果是头节点,相当于更新head指针,让它跳过被删除的节点;如果是中间节点,p此时指向的是前一个节点的next成员的地址,修改*p就是让前一个节点的next直接指向被删除节点的下一个节点,完美维护了链表的链接。 - 如果不需要删除,就把
p移动到当前节点的next成员的地址,继续遍历。
核心差异
两段代码的本质区别在于是否能修改链表的指针引用:
- 第一段代码的
ptr是普通指针,它仅存储节点的地址,但修改ptr不会影响链表本身的指针(比如head或其他节点的next),删除节点后,前驱节点的next依然指向已释放的内存,导致断链。 - 第二段代码的
p是指向指针的指针,它直接指向链表中用来记录下一个节点地址的“容器”(要么是head变量,要么是节点的next成员),删除时直接修改这个容器里的地址,让链表的链接关系被正确更新,从根源上避免了断链。
内容的提问来源于stack exchange,提问作者Klau
相关产品推荐
相关产品推荐

