news 2026/3/9 13:36:31

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/3/1 14:55:58

GEO战略解码:AI搜索时代,如何重构品牌认知的底层逻辑

摘要当用户向DeepSeek询问“B2B供应链金融解决方案”时&#xff0c;AI直接整合并推荐了三个品牌及其核心优势&#xff0c;而你的品牌未被提及——这意味着在AI定义的新世界里&#xff0c;你的品牌已经“主动隐身”。本文旨在为数字营销负责人、CMO及战略规划者提供一份深度指南…

作者头像 李华
网站建设 2026/3/7 5:25:25

【小白笔记】删除排序链表中的重复元素(I 和II)

这道题充分利用了链表便于删除节点的特性&#xff0c;以及题目给出的**“已排序”**这个关键前提。1. 解题思路&#xff1a;一次遍历 由于链表是已排序的&#xff0c;所有重复的元素在物理位置上一定是相邻的。 初始化&#xff1a;让一个指针 cur 指向 head。比较与去重&#x…

作者头像 李华
网站建设 2026/2/26 12:45:40

【小白笔记】无重复字符的最长子串和长度最小的子数组(滑动窗口中两种不同的“窗口控制策略)

这个问题是 “滑动窗口 (Sliding Window)” 算法的顶级经典题。 在处理“最长子串”、“子数组”等问题时&#xff0c;滑动窗口能够将复杂度从 O(N2)O(N^2)O(N2) 降低到 O(N)O(N)O(N)。1. 核心思路&#xff1a;滑动窗口 想象字符串上有一个可以伸缩的窗口&#xff1a; 右边界 (…

作者头像 李华
网站建设 2026/3/8 18:26:56

β-Amyloid (1-40), Rat;DAEFGHDSGFEVRHQKLVFFAEDVGSNKGAIIGLMVGGVV

一、基本信息英文名称&#xff1a;β-Amyloid (1-40), Rat&#xff1b;Amyloid β-Protein (1-40), Rat&#xff1b;Rat Aβ1-40中文名称&#xff1a;大鼠源 β- 淀粉样蛋白 (1-40)&#xff1b;大鼠 β- 淀粉样肽 (1-40)单字母多肽序列&#xff1a;DAEFGHDSGFEVRHQKLVFFAEDVGSN…

作者头像 李华
网站建设 2026/3/4 8:13:49

海外回国eSIM避坑指南一定要提前搞懂,不然真的会被坑惨!

每次从海外回国&#xff0c;&#x1f4f6;上网问题永远是一个焦虑源尤其是用eSIM的宝子们只要一步踩雷&#xff0c;真的回国第一天就寸步难行&#xff01;这篇给宝子一次讲清楚&#xff1a;海外回国&#xff0c;用eSIM经常踩的坑正确避坑方式&#x1f447;1️⃣回国前先确认&am…

作者头像 李华
网站建设 2026/3/8 10:56:08

Wan2.2-T2V-A14B模型部署与高保真T2V实战

Wan2.2-T2V-A14B模型部署与高保真T2V实战&#xff1a;从零构建专业级视频生成系统 你有没有试过这样一种场景——脑中浮现出一个极具电影感的画面&#xff1a;“一只机械狐狸在雪原上跃起&#xff0c;身后是崩塌的未来城市&#xff0c;闪电划破铅灰色天空”&#xff0c;但当你试…

作者头像 李华