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
相关产品推荐
相关产品推荐

