You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

双向链表节点删除代码调试求助:首节点删除失败且头尾指针未更新

双向链表删除节点问题的修复方案

核心问题分析

你的代码存在以下几个关键问题:

  • 指针传递方式错误: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;
}

关键修复点说明

  1. 指针传引用:将 deleteNode 的参数改为 Node*& head 和 Node*& tail,确保函数内对指针的修改能同步到外部。
  2. 修正析构函数:移除 delete next 语句,避免删除当前节点时递归释放后续所有节点。
  3. 处理唯一节点:删除首节点时判断是否为唯一节点,同步清空 head 和 tail。
  4. 更新尾指针:删除尾节点时将 tail 指向倒数第二个节点。
  5. 完善中间节点删除逻辑:删除中间节点时,不仅更新前节点的 next,还要更新后节点的 prev,保证链表的双向链接完整性。
  6. 位置合法性检查:遍历过程中判断 curr 是否为空,避免访问超出链表长度的无效位置。

内容的提问来源于stack exchange,提问作者Priyanshi Babbar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 21:36:26