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

C++自定义链表中用户输入节点的删除方法及STL List学习疑问

单链表节点删除实现及STL list底层原理解析

首先得先把你当前的输入函数逻辑理顺,不然连正常的链表都构建不出来,更别说删除节点了:

修复后的输入函数

你的takeinput存在几个明显问题:只读取一次num、创建节点时var未赋值、输入流程逻辑混乱,修复后代码如下:

#include <iostream>
#include <string>

using namespace std;

class Node {
public:
    string todos;
    Node* next;

    Node(string todos) {
        this->todos = todos;
        next = nullptr; // 用nullptr替代NULL更规范
    }
};

void print_list(Node* head) {
    Node* temp = head;
    while (temp != nullptr) {
        cout << temp->todos << " ";
        temp = temp->next;
    }
    cout << endl;
}

Node* takeinput() {
    string var;
    int num;

    Node* head = nullptr;
    Node* tail = nullptr;

    cout << "请输入操作:" << endl;
    cout << "1. 添加待办任务" << endl;
    cout << "2. 删除待办任务(暂未实现,先完成输入)" << endl;
    cout << "输入'End'结束输入" << endl << endl;

    while (true) {
        cout << "请选择操作:";
        if (!(cin >> num)) {
            cin.clear();
            cin.ignore();
            string input;
            cin >> input;
            if (input == "End") break;
            else {
                cout << "无效输入,请重新选择" << endl;
                continue;
            }
        }

        if (num == 1) {
            cout << "请输入待办内容:";
            cin >> var;
            Node* newNode = new Node(var);
            if (head == nullptr) {
                head = newNode;
                tail = newNode;
            } else {
                tail->next = newNode;
                tail = newNode;
            }
            cout << "已添加:" << var << endl;
        } else if (num == 2) {
            // 后续可以在这里调用删除函数
            cout << "删除功能待实现" << endl;
        } else {
            cout << "无效操作,请重新选择" << endl;
        }
    }
    return head;
}

单链表删除节点的核心实现

单链表的删除逻辑要分三种场景处理,核心是调整指针指向+释放节点内存:

1. 按值删除节点

实现一个根据待办内容删除节点的函数,需要遍历链表找到目标节点的前驱:

Node* deleteByValue(Node* head, const string& target) {
    // 情况1:删除头节点
    if (head != nullptr && head->todos == target) {
        Node* temp = head;
        head = head->next;
        delete temp; // 释放内存,避免泄漏
        return head;
    }

    // 情况2:删除中间或尾节点
    Node* curr = head;
    Node* prev = nullptr;
    while (curr != nullptr && curr->todos != target) {
        prev = curr;
        curr = curr->next;
    }

    // 没找到目标节点
    if (curr == nullptr) {
        cout << "未找到待删除的任务" << endl;
        return head;
    }

    // 调整指针
    prev->next = curr->next;
    delete curr;
    return head;
}

2. 按位置删除节点

如果知道要删除的节点位置(从0开始计数),可以这样实现:

Node* deleteByPosition(Node* head, int pos) {
    if (head == nullptr) {
        cout << "链表为空,无法删除" << endl;
        return head;
    }

    // 情况1:删除头节点
    if (pos == 0) {
        Node* temp = head;
        head = head->next;
        delete temp;
        return head;
    }

    // 找到目标位置的前驱节点
    Node* prev = head;
    for (int i = 0; i < pos - 1 && prev != nullptr; i++) {
        prev = prev->next;
    }

    // 位置超出链表长度
    if (prev == nullptr || prev->next == nullptr) {
        cout << "位置无效" << endl;
        return head;
    }

    // 情况2:删除中间或尾节点
    Node* temp = prev->next;
    prev->next = temp->next;
    delete temp;
    return head;
}

在main函数中调用删除功能

修改main函数,添加删除逻辑:

int main() {
    Node* head = takeinput();
    cout << endl << "当前链表内容:";
    print_list(head);

    // 示例:按值删除
    string target;
    cout << endl << "请输入要删除的任务:";
    cin >> target;
    head = deleteByValue(head, target);
    cout << "删除后的链表:";
    print_list(head);

    // 示例:按位置删除
    int pos;
    cout << endl << "请输入要删除的位置(从0开始):";
    cin >> pos;
    head = deleteByPosition(head, pos);
    cout << "删除后的链表:";
    print_list(head);

    // 最后记得释放整个链表内存,避免泄漏
    Node* temp;
    while (head != nullptr) {
        temp = head;
        head = head->next;
        delete temp;
    }

    return 0;
}

STL list的底层实现和单链表的区别

你在学STL list的底层,它和你实现的单链表核心差异在于:

  • STL list是双向循环链表,每个节点包含prev和next两个指针,分别指向前后节点,链表首尾相连(尾节点的next指向头节点,头节点的prev指向尾节点)
  • 因为是双向链表,删除节点时不需要遍历找前驱,直接通过节点的prev和next调整指针即可,时间复杂度是O(1)(单链表是O(n))
  • STL list通常维护一个哨兵节点(dummy node),避免单独处理头/尾节点的边界情况,所有节点都作为哨兵节点的前后节点,代码逻辑更简洁
  • STL list的迭代器是双向迭代器,支持向前/向后遍历,而单链表只能单向遍历

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:35:41