用裸指针手写双向链表需严格维护prev/next对称性:插入须同步更新前后节点四向指针;删除要先保存邻节点再修复双向链接;反转只需遍历交换各节点prev/next并swap头尾指针,时间O(n)、空间O(1)。

如何用C++手写一个支持插入、删除、反转的双向链表
直接说结论:用裸指针实现比依赖std::list更可控,但必须手动管理prev和next指针的对称性——漏掉任一端,就会导致遍历崩溃或内存泄漏。
插入操作必须同时更新前后节点的指针
在任意位置(头、尾、中间)插入新节点时,仅改当前节点的prev/next远远不够。比如在节点A后插入B,需同步调整:A→next、B→prev、B→next、A→next→prev(如果A→next非空)。
- 头插:更新
head→prev(若原head非空),再设新节点next = head,最后head = newNode - 尾插:类似,但要先找到
tail,或维护tail指针;否则遍历到末尾再插,时间复杂度升为O(n) - 中间插:务必检查
pos->next是否为空——否则pos->next->prev = newNode会解引用空指针
删除节点前必须修复邻居指针,且要处理头/尾特例
删节点target时,若只改target->prev->next = target->next,而忘了target->next->prev = target->prev,后续反向遍历就会跳过或崩溃。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 删头节点:
head = head->next后,若新head非空,必须head->prev = nullptr - 删尾节点:同理,
tail = tail->prev后,若新tail非空,则tail->next = nullptr - 通用删除:先保存
target->prev和target->next,再分别更新它们的反向指针,最后delete target - 常见错误:
if (target == head) head = target->next;之后没清head->prev,导致头节点prev指向已释放内存
反转链表只需交换每个节点的prev/next,无需新建节点
反转本质是把整条链的“方向”翻转,不是复制数据。最简做法:遍历一次,对每个节点交换其prev和next指针,最后交换head和tail指针值。
立即学习“C++免费学习笔记(深入)”;
- 不能只遍历一半:双向链表反转后,所有节点的逻辑关系都变了,必须全扫一遍
- 注意边界:当
head == tail(单节点)或head == nullptr时,直接返回,避免空指针解引用 - 别漏交换头尾:
std::swap(head, tail)比手动赋值更安全,防止临时变量出错 - 性能友好:时间
O(n)、空间O(1),比重建链表或用栈辅助更高效
真正难的不是写完代码,而是每次修改指针时,都得在脑中画出四个箭头(前驱的next、自身的prev/next、后继的prev)是否全部指向正确位置。少验一个,运行时就可能崩在第100次插入之后。

















