双链表结点定义如下,若要删除双链表中的中间结点(非首尾节点)p,下面写法正确的是( )。
struct Node {
int val;
Node* prev;
Node* next;
};仔细审题,明确已知条件和所求目标,运用相关知识点逐项分析。
审题时注意题目要求(选正确还是选错误),避免因审题不清失分。涉及代码的题目要逐行分析变量变化。
【考点】双链表指针操作|内存管理|节点删除逻辑
🎯 考纲定位 本题考查《GESP 考试大纲》五级"数据结构"模块中双链表的核心操作。命题人放这道题就一个目的:卡住那些只背过单链表删除、对双链表指针方向概念模糊的考生——双链表删除必须同时维护 prev 和 next 两条链,任何一条没改,链表就断了。
🧠 解题思维 删除中间结点 p 的标准步骤:先绕过它再释放。关键观察是双链表有两条路径,必须按顺序更新,否则 p 的某个指针会丢失。正确链条:p->prev->next = p->next; p->next->prev = p->prev; delete p; 第一步让 p 的前驱跳过 p 指向后继,第二步让 p 的后继反过来指向前驱,最后 p 成了悬空结点。这一类题的通法是:双链删除永远先改两条邻接指针,再 delete,顺序不能乱。
🪤 陷阱拆解 B 选项把两个赋值顺序颠倒且逻辑全错:p->next->prev = p->next 等于把后继的 prev 指向自己,毫无意义;p->prev->next = p->prev 又把前驱的 next 指向自己,链表彻底断裂。C 选项更离谱:p->prev = p->next; p->next = p->prev; delete p; 只是让 p 的两个指针互相引用,完全没动链表,delete p 后链表少一个节点但其余不变。D 选项偷换概念:它改的是 p->next->next 和 p->prev->prev,那是 p 的后继的后继和前驱的前驱,跟删除 p 毫无关系。最阴险的是"delete p"的位置——放在前面就会先释放 p,后面访问 p->prev 或 p->next 就是野指针,这是 C++ 最经典的悬空引用陷阱。
🔄 反命题思维 如果把题目改成"删除头结点",选项就得加判断 p->prev 是否空;改成"删除尾结点",就要看 p->next 是否空;再极端一点,改成"删除任意结点",就得先遍历找到它。刷到类似题先问自己:命题人想考我双链表的方向感,还是内存管理,还是边界条件?