当前位置: 首页 > news >正文

C++实现带头双向链表高效增删查改

C++:带头双向链表增删查改模拟实现

带头双向链表是一种常见的数据结构,它包含一个头节点(dummy node),该节点不存储实际数据,仅用于简化链表操作。每个节点都有prevnext指针,指向前后节点,实现双向遍历。这种结构在插入和删除操作时效率较高,因为可以直接访问相邻节点。下面我将逐步实现带头双向链表的增(insert)、删(delete)、查(find)、改(modify)操作。

实现思路
  1. 节点类(Node):定义链表节点,包含数据(data)、前驱指针(prev)和后继指针(next)。
  2. 链表类(List):管理链表,包含头节点和成员函数。
    • 头节点初始化时指向自己,形成循环。
    • 实现增删查改操作,注意指针更新和边界处理。
  3. 内存管理:使用动态分配内存,需在析构函数中释放节点,避免泄漏。

以下是完整的C++代码实现,包含注释解释关键步骤:

#include <iostream> // 用于输入输出 // 节点类模板 template <typename T> class Node { public: T data; // 存储数据 Node* prev; // 前驱指针 Node* next; // 后继指针 // 构造函数 Node(T val) : data(val), prev(nullptr), next(nullptr) {} }; // 带头双向链表类模板 template <typename T> class List { private: Node<T>* head; // 头节点(哨兵节点) public: // 构造函数:初始化头节点 List() { head = new Node<T>(T()); // 创建头节点,数据使用默认值 head->prev = head; // 初始时,头节点指向自己 head->next = head; } // 析构函数:释放所有节点内存 ~List() { Node<T>* current = head->next; while (current != head) { // 遍历链表 Node<T>* nextNode = current->next; delete current; // 释放当前节点 current = nextNode; } delete head; // 释放头节点 } // 增:在指定位置插入节点(位置从0开始,0表示头节点后第一个位置) void insert(T val, int pos) { if (pos < 0) return; // 位置无效,直接返回 Node<T>* newNode = new Node<T>(val); // 创建新节点 Node<T>* current = head->next; // 当前节点从第一个实际节点开始 int count = 0; // 遍历找到插入位置的前驱节点 while (current != head && count < pos) { current = current->next; count++; } // 插入新节点:更新指针 newNode->prev = current->prev; newNode->next = current; current->prev->next = newNode; current->prev = newNode; } // 删:删除指定位置的节点 void deleteNode(int pos) { if (pos < 0) return; // 位置无效,直接返回 Node<T>* current = head->next; int count = 0; // 遍历找到要删除的节点 while (current != head && count < pos) { current = current->next; count++; } if (current == head) return; // 位置超出链表范围 // 删除节点:更新指针并释放内存 current->prev->next = current->next; current->next->prev = current->prev; delete current; } // 查:查找指定值的节点,返回节点指针(若不存在返回nullptr) Node<T>* find(T val) { Node<T>* current = head->next; // 从头节点后开始遍历 while (current != head) { if (current->data == val) { return current; // 找到匹配节点 } current = current->next; } return nullptr; // 未找到 } // 改:修改指定位置节点的值 void modify(int pos, T newVal) { if (pos < 0) return; // 位置无效,直接返回 Node<T>* current = head->next; int count = 0; // 遍历找到要修改的节点 while (current != head && count < pos) { current = current->next; count++; } if (current != head) { current->data = newVal; // 修改数据 } } // 打印链表:用于测试 void print() { Node<T>* current = head->next; // 跳过头节点 std::cout << "链表: "; while (current != head) { std::cout << current->data << " "; current = current->next; } std::cout << std::endl; } }; // 测试示例 int main() { List<int> list; list.insert(10, 0); // 插入到位置0 list.insert(20, 1); // 插入到位置1 list.insert(30, 2); // 插入到位置2 list.print(); // 输出: 链表: 10 20 30 list.deleteNode(1); // 删除位置1的节点 list.print(); // 输出: 链表: 10 30 Node<int>* found = list.find(30); // 查找值为30的节点 if (found) { std::cout << "找到节点: " << found->data << std::endl; // 输出: 找到节点: 30 } list.modify(0, 50); // 修改位置0的节点值为50 list.print(); // 输出: 链表: 50 30 return 0; }
代码解释
  • 头节点:在构造函数中初始化,head->prevhead->next都指向自身,形成循环结构,简化边界条件处理。
  • 插入操作(insert):遍历到指定位置,更新新节点和相邻节点的指针。时间复杂度为$O(n)$,最坏情况下需遍历链表。
  • 删除操作(deleteNode):找到节点后,更新指针并释放内存。时间复杂度为$O(n)$。
  • 查找操作(find):遍历链表比较值,返回节点指针。时间复杂度为$O(n)$。
  • 修改操作(modify):直接修改指定位置节点的数据。时间复杂度为$O(n)$。
  • 打印操作(print):用于测试链表内容。
  • 内存安全:析构函数释放所有节点,避免内存泄漏。
使用说明
  • 上述代码是模板类实现,支持任意数据类型(如int,double,string)。
  • 测试示例在main函数中展示了基本操作。
  • 带头双向链表适用于频繁插入和删除的场景,如缓存或队列实现。您可以根据需求扩展其他功能,如大小获取或迭代器。

如果您有具体问题或需要进一步优化,请随时提问!

http://www.jsqmd.com/news/669751/

相关文章:

  • c语言指的是什么意思
  • Internet Protocol Version 8(IPv8)技术草案
  • 浅学线性回归与逻辑回归
  • 降AI率工具哪个好上手?嘎嘎降AI从注册到出结果完整教程
  • 从源头杜绝损坏!EV录屏高手都在用的MKV格式录制与无损修复全攻略
  • DAMO-YOLO手机检测结果结构化解析:JSON输出格式与数据库存储设计
  • 【Gazebo进阶指南】仿真调试利器:日志记录与场景复现实战
  • LobeChat应用指南:如何利用可扩展插件,定制个性化机器人?
  • 2026机场护栏网厂家推荐 产能规模与专利技术双领先(产能+专利+服务) - 爱采购寻源宝典
  • 算法4.19好题推荐
  • 移动端未来:探讨Qwen3-ForcedAligner-0.6B在Android端的量化部署可能
  • PyTorch 2.8 镜像下的C++扩展开发指南:提升模型推理性能
  • 5步搞定Gemma-3-12B-IT:无需代码基础,快速搭建AI对话平台
  • 别再手动拔跳线帽了!STM32串口下载的BootLoader原理与一键下载电路实战(FlyMcu配置详解)
  • 雪女-斗罗大陆-造相Z-Turbo环境配置进阶:Ubuntu系统依赖深度解析
  • 2026护栏网厂家推荐排行榜产能与专利双优的权威选择 - 爱采购寻源宝典
  • Wan2.2-I2V-A14B多场景应用:跨境电商商品多角度展示视频自动生成
  • 不止于TSP:用Python+LKH算法解决车辆路径规划(VRP)问题的思路与代码示例
  • Janus-Pro-7B赋能运维可视化:自动生成服务器监控图表分析报告
  • Python Web应用负载均衡方案_结合Nginx权重设置实现高可用
  • Ollama+DeepSeek-R1实战:快速部署推理模型,解决复杂问题
  • 从正则表达式到词法分析器:图解NFA确定化与最小化的完整工作流
  • RexUniNLU在STM32嵌入式系统的轻量化部署方案
  • 告别virt-manager!纯命令行搞定KVM虚拟机创建与管理(附常用命令清单)
  • Qwen3-TTS声音克隆应用指南:快速搭建智能客服语音系统
  • HY-MT1.5-1.8B翻译模型优化:提升推理速度的3个技巧
  • 索尼相机功能解锁终极指南:OpenMemories-Tweak完全解析
  • Android 单 Activity 架构下的 Splash Screen 与主题规范指南
  • 基于RetinaFace的Web应用开发:人脸特征提取与分析
  • 从采购入库到工单发料:一份SAP BAPI_GOODSMVT_CREATE的实战代码模板合集(含101/261/344等移动类型)