news 2026/9/24 12:59:41

c++ STL容器之list 实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
c++ STL容器之list 实现

代码中的注释已经写的比较清楚了,就直接上代码吧

#include <iostream> // 节点定义 template<typename T> struct ListNode { ListNode *prev; ListNode *next; T data; }; template<typename T> class MyList { private: using Node = ListNode<T>; public: /** * iterator类作用 * 如果没有iterator类,则MyList类对外暴露Node*类型,用户可以自定义操作节点 * 现在是用iterator类,封装指针节点的指针,通过运算符重载只给用户提供遍历和访问的能力 * 从而屏蔽容器内部的节点结构,禁止用户直接操作节点。 * */ class iterator { public: iterator(Node* n = nullptr) : _node(n) {} T& operator*() const {return _node->data;} T* operator->() const {return &_node->data;} iterator& operator++() { _node = _node->next; return *this; } iterator operator++(int) { iterator t = *this; ++(*this); return t; } iterator& operator--() { _node = _node->prev; return *this; } bool operator==(const iterator& obj) const { return _node == obj._node; } bool operator!=(const iterator& obj) const { return _node != obj._node; } friend class MyList; private: Node *_node; }; /** * 限制“通过迭代器访问元素的能力”,而不是容器或节点本身是否可修改。 */ class const_iterator { public: const_iterator(Node *n = nullptr): _node(n) {} const_iterator(const iterator& it) : _node(it._node) {} const T& operator*() const {return _node->data;} const T* operator->() const {return &_node->data;} const_iterator& operator++() { _node = _node->next; return *this; } const_iterator operator++(int) { const_iterator t = *this; ++(*this); return t; } const_iterator& operator--() { _node = _node->prev; return *this; } bool operator==(const const_iterator& obj) const { return _node == obj._node; } bool operator!=(const const_iterator& obj) const { return _node != obj._node; } friend class MyList; private: Node *_node; }; public: MyList() : _size(0) { _head = new Node; _head->next = _head; _head->prev = _head; } ~MyList() { clear(); delete _head; } bool empty() const {return _size == 0;} size_t size() const {return _size;} iterator begin() {return iterator(_head->next);} const_iterator begin() const {return const_iterator(_head->next);} iterator end() {return iterator(_head);} // 返回最后一个元素前一个位置 const_iterator end() const {return const_iterator(_head);} // 在 pos 前面插入新节点 O(1) void insert(iterator pos, const T &val) { Node *cur = pos._node; Node* prev = cur->prev; Node *n = new Node; n->data = val; // 分别指向前后节点 n->next = cur; n->prev = prev; // 前一个的下一个节点为当前插入的节点 prev->next = n; // 在当前节点之前插入,则前置指针指向新的节点 cur->prev = n; ++_size; } // 清除当前节点 iterator erase(iterator pos) { Node * cur = pos._node; Node * prev = cur->prev; Node * next = cur->next; // 上一个与下一个节点都取消对当前节点的指向 prev->next = next; next->prev = prev; delete cur; --_size; return iterator(next); // 删除当前节点之后,下一个节点按顺序变为这个位置的节点 } void push_back(const T&val) { insert(end(),val); // 直接调用inset 方法,在末尾直接插入 } void push_front(const T&val) { insert(begin(),val); //front 在表头插入 } void pop_back() { erase(--end()); // 删除表尾 } void pop_front() { erase(begin()); // 删除表头 } void clear() { Node * cur = _head->next; while(cur != _head) { Node* next = cur->next; delete cur; cur = next; } _head->next = _head; _head->prev = _head; _size = 0; } /** * splice 含义: * 不拷贝、不构造、不析构元素, * 仅通过修改指针,把节点从一个 list 挂到另一个 list。 * 本质是:“改链表结构,而不是操作元素” 即直接修改指针 * */ // 把 other 中 [first, last) 区间移动到 pos 前 void splice(iterator pos,MyList &other,iterator first,iterator last) { if (first == last) return; // 如果 pos 落在 [first, last) 区间内 什么也不做 /** * 处理自己与自己的元素移动 self-splice * list:0 1 2 3 _head <-> 0 <-> 1 <-> 2 <-> 3 <-> _head * 例如传递参数(begin(),list,begin(),begin() + 1) 即把[0,1)区间的元素移动到0之前 * 当没有下面的判断则会: * firstNode = &0 lastNode = &1 lastPrev = &0 * firstNode->prev->next = lastNode * lastNode->prev = firstNode->prev; * 相当于 _head <-> 1 <-> 2 <-> 3 <-> _head, _head<- 0 ->1 通过链表已经找不到0元素了 * * posNode = &0 posPrev = _head; * posPrev->next = firstNode; * 相当于 _head -> 0 -> 1 <-> 2 <-> 3 <-> _head , 但是_head <- 1; 1前驱变为_head * * firstNode->prev = posPrev; * 相当于 _head <-> 0 -> 1 <-> 2 <-> 3 <-> _head , _head <- 1; * * 错误点: * lastPrev->next = posNode; * posNode->prev = lastPrev; * 0 与 0 产生自环 0 <-> 0 * 0 的前驱也指向自己,与_head断开,即链表元素变为 1 <-> 2 <-> 3, 1 <- _head,3 -> _head */ if(this == &other) { for(auto it = first; it != last; it++) { if (it == pos) return; } } Node *firstNode = first._node; Node *lastNode = last._node; Node *lastPrev = lastNode->prev; // [first, last) 之中的节点从整个链表中脱离 firstNode->prev->next = lastNode; lastNode->prev = firstNode->prev; // 将[first, last)指针指向ops之前 Node *posNode = pos._node; Node *posPrev = posNode->prev; // 修改first指向与lastpre指向 posPrev->next = firstNode; firstNode->prev = posPrev; lastPrev->next = posNode; posNode->prev = lastPrev; // 修改size size_t cnt = 0; for(auto it = first; it != last; it++) cnt += 1; _size += cnt; other._size -= cnt; } // 把 other 整个移动到pos前 void splice(iterator pos, MyList& other) { if (other.empty()) return; splice(pos, other, other.begin(), other.end()); } //把 other 中 it 指向的一个节点移动到 pos 前 void splice(iterator pos, MyList& other, iterator it) { iterator next = it; ++next; // [it,next) 区间直接移动 splice(pos, other, it, next); } private: Node *_head; // 头节点 size_t _size; };
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 0:52:24

【源码开源】基于STM32的应急救援仓系统 | 救援效率和实时监控

【源码开源】基于STM32的应急救援仓系统 | 救援效率和实时监控 前言 随着城市化进程的加快&#xff0c;自然灾害和突发公共事件的频发&#xff0c;应急救援系统在保障民众生命财产安全方面显得尤为重要。传统的应急救援仓多依赖人工巡查&#xff0c;效率低且信息获取滞后。为…

作者头像 李华
网站建设 2026/9/24 23:17:33

【开源源码】基于 STM32智能温度监控系统 | 一个支持远程监控与告警的嵌入式实践项目

基于 STM32 和 μC/OS 的智能温度监控系统设计与实现 ——一个支持远程监控与告警的嵌入式实践项目 随着物联网与智能硬件的发展&#xff0c;环境监控系统已经成为工业、农业、智能家居等领域的重要组成部分。其中&#xff0c;温度监控作为最基础的参数采集手段&#xff0c;其…

作者头像 李华
网站建设 2026/9/24 18:26:27

【小白笔记】大数加法

“大数加法”是面试和算法练习中非常经典的一道题&#xff08;如 LeetCode 415&#xff09;。它的核心矛盾在于&#xff1a;计算机的标准整数类型&#xff08;如 64 位整型&#xff09;有最大值限制&#xff0c;当数字超过几十位甚至上百位时&#xff0c;直接相加会溢出。 处理…

作者头像 李华
网站建设 2026/9/25 11:18:34

课题申报新手入门必备指南!利用AI辅助搞定 6大关键部分,高效提升申报成功率(附AI提示词)

课题申报已经成为不少教师同仁职业发展、职称评比的必要条件之一,但很多新手老师仍不知道该从何下手。对于厚厚的申报指南和复杂的评审指标,不少教师虽然有研究想法,但卡在选题、创新点等关键环节上。 今天七哥带各位老师将申报书彻底拆解,弄清楚各部分写作技巧,并搭配AI…

作者头像 李华
网站建设 2026/9/25 11:18:27

Advanced Database Cleaner - WordPress数据库清理优化插件

‌Advanced Database Cleaner Pro 是一款专为WordPress设计的数据库清理与优化插件&#xff0c;主要用于删除冗余数据、孤立表、过期瞬态等&#xff0c;以提升网站性能和数据库效率‌。 如果您已经使用WordPress一段时间了&#xff0c;那么您可以考虑一下清理工作。您的数据库…

作者头像 李华
网站建设 2026/9/24 11:53:12

2025 年 12 月找靠谱中国 AI 智能体获客老师,麟哥难道不称职?

一、2025 ai 获客培训市场&#xff1a;讲师选择的核心参考维度2025 年 ai 智能体获客领域的技术迭代&#xff0c;正从通用大模型应用转向垂直场景深度适配。企业在筛选培训讲师时&#xff0c;已逐步跳出单纯的工具操作教学需求&#xff0c;更关注讲师的技术积累、知识体系完整性…

作者头像 李华