双向链表节点删除代码调试求助:首节点删除失败且头尾指针未更新
双向链表删除节点问题的修复方案
核心问题分析
你的代码存在以下几个关键问题:
- 指针传递方式错误:
deleteNode函数中head按值传递,函数内对head的修改无法同步到main中的原始指针。 - 未处理
tail指针更新:删除尾节点或唯一节点时,tail指针没有被正确更新。 - 析构函数引发链式删除:Node类的析构函数会递归删除后续节点,导致意外释放整个链表的内存。
- 边界情况未处理:删除唯一节点时访问
temp->next->prev会触发空指针错误;删除中间节点时未正确更新后续节点的prev指针。
修复后的完整代码
#include <iostream> using namespace std; class Node{ public: int data; Node* prev; Node* next; // 构造函数 Node(int d) { this->data = d; this->prev = NULL; this->next = NULL; } // 修复后的析构函数:仅释放当前节点,避免链式删除 ~Node() { int val = this->data; cout << "memory free for node with data " << val << endl; } }; // 头插法实现 void insertAtHead(Node*& head, Node*& tail, int d) { Node* temp = new Node(d); if (head == NULL) { head = temp; tail = temp; } else { temp->next = head; head->prev = temp; head = temp; } } // 尾插法实现 void insertAtTail(Node*& head, Node*& tail, int d) { Node* temp = new Node(d); if (tail == NULL) { head = temp; tail = temp; } else { tail->next = temp; temp->prev = tail; tail = temp; } } // 指定位置插入实现 void insertAtPosition(Node*& head, Node*& tail, int pos, int d) { if (pos == 1) { insertAtHead(head, tail, d); return; } Node* curr = head; int cnt = 1; while (cnt < pos-1 && curr != NULL) { curr = curr->next; cnt++; } if (curr == NULL) { cout << "Invalid position" << endl; return; } if (curr == tail) { insertAtTail(head, tail, d); return; } Node* temp = new Node(d); temp->next = curr->next; curr->next->prev = temp; curr->next = temp; temp->prev = curr; } // 打印链表实现 void print(Node* head) { Node* temp = head; while (temp != NULL) { cout << temp->data << " "; temp = temp->next; } cout << endl; } // 修复后的删除节点函数 void deleteNode(int position, Node*& head, Node*& tail) { // 空链表判断 if (head == NULL) { cout << "List is empty, nothing to delete" << endl; return; } // 删除首节点 if (position == 1) { Node* temp = head; // 非唯一节点情况 if (temp->next != NULL) { temp->next->prev = NULL; head = temp->next; } else { // 唯一节点,同时清空head和tail head = NULL; tail = NULL; } temp->next = NULL; delete temp; } else { // 删除中间或尾节点 Node* curr = head; Node* prevNode = NULL; int cnt = 1; // 定位目标节点,同时防止位置越界 while (cnt < position && curr != NULL) { prevNode = curr; curr = curr->next; cnt++; } // 无效位置判断 if (curr == NULL) { cout << "Invalid position" << endl; return; } // 尾节点处理:更新tail指针 if (curr == tail) { tail = prevNode; prevNode->next = NULL; } else { // 中间节点处理:更新后续节点的prev指针 curr->next->prev = prevNode; prevNode->next = curr->next; } // 断开目标节点的链接 curr->prev = NULL; curr->next = NULL; delete curr; } } int main() { Node* head = NULL; Node* tail = NULL; insertAtHead(head, tail, 11); insertAtHead(head, tail, 18); insertAtHead(head, tail, 9); cout << "Initial list: "; print(head); insertAtTail(head, tail, 21); insertAtPosition(head, tail, 2, 34); cout << "After insertions: "; print(head); // 删除首节点,传递head和tail的引用 deleteNode(1, head, tail); cout << "After deleting position 1: "; print(head); cout << "head - " << head->data << endl; cout << "tail - " << tail->data << endl; // 测试删除尾节点 deleteNode(4, head, tail); cout << "After deleting tail: "; print(head); cout << "head - " << head->data << endl; cout << "tail - " << tail->data << endl; return 0; }
关键修复点说明
- 指针传引用:将
deleteNode的参数改为Node*& head和Node*& tail,确保函数内对指针的修改能同步到外部。 - 修正析构函数:移除
delete next语句,避免删除当前节点时递归释放后续所有节点。 - 处理唯一节点:删除首节点时判断是否为唯一节点,同步清空
head和tail。 - 更新尾指针:删除尾节点时将
tail指向倒数第二个节点。 - 完善中间节点删除逻辑:删除中间节点时,不仅更新前节点的
next,还要更新后节点的prev,保证链表的双向链接完整性。 - 位置合法性检查:遍历过程中判断
curr是否为空,避免访问超出链表长度的无效位置。
内容的提问来源于stack exchange,提问作者Priyanshi Babbar
相关产品推荐
相关产品推荐

