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

手撕C++ list容器:从节点到完整双向链表实现

前言

在C++标准模板库(STL)中,list是一个非常重要的容器,它实现了双向链表的数据结构。本文将深入探讨如何从零开始实现一个完整的list容器,包括节点设计、迭代器实现和核心功能。

整体结构设计

节点设计

首先我们需要定义链表的基本单元——节点:

cpp

template<class T>
struct list_node
{T _val;list_node<T>* _prev;list_node<T>* _next;list_node(const T& val = T()): _val(val), _prev(nullptr), _next(nullptr){}
};

每个节点包含三个部分:

  • _val: 存储数据值

  • _prev: 指向前一个节点的指针

  • _next: 指向后一个节点的指针

迭代器设计

迭代器是容器的"智能指针",我们使用模板技巧实现iteratorconst_iterator

cpp

template<class T, class Ref, class Ptr>
struct list_iterator
{typedef list_node<T> Node;typedef list_iterator<T, Ref, Ptr> Self;Node* _node;// 构造函数和运算符重载...
};

这种设计巧妙之处在于通过模板参数RefPtr区分普通迭代器和常量迭代器:

  • iteratorlist_iterator<T, T&, T*>

  • const_iteratorlist_iterator<T, const T&, const T*>

核心实现解析

构造函数与初始化

cpp

list()
{empty_init();
}void empty_init()
{_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;
}

这里使用了哨兵节点(头节点)技术,让链表形成环形结构,简化边界条件处理。

拷贝控制:拷贝构造与赋值

cpp

// 拷贝构造函数
list(const list<T>& lt)
{empty_init();for (auto& e : lt){push_back(e);}
}// 赋值运算符(使用Copy-and-Swap技术)
list<T>& operator=(list<T> it)
{swap(it);return *this;
}void swap(list<T>& it)
{std::swap(_head, it._head);std::swap(_size, it._size);
}

赋值运算符采用传值方式,这实现了Copy-and-Swap惯用法:

  1. 参数it通过传值接收(可能是拷贝或移动构造)

  2. 交换当前对象与参数的内容

  3. 返回时参数自动析构,释放旧资源

这种方法异常安全且代码简洁,同时支持拷贝和移动赋值。

迭代器操作

cpp

iterator begin() { return _head->_next; }
iterator end() { return _head; }const_iterator begin() const { return _head->_next; }
const_iterator end() const { return _head; }

迭代器范围是左闭右开区间[begin, end)end()返回头节点,符合STL惯例。

元素访问与修改

cpp

// 插入操作
void insert(iterator pos, const T& x)
{Node* newnode = new Node(x);newnode->_prev = pos._node->_prev;newnode->_next = pos._node;pos._node->_prev->_next = newnode;pos._node->_prev = newnode;_size++;
}// 删除操作
iterator erase(iterator pos)
{assert(pos != end());Node* next_node = pos._node->_next;pos._node->_prev->_next = pos._node->_next;pos._node->_next->_prev = pos._node->_prev;delete pos._node;_size--;return next_node;
}

erase()函数返回下一个有效迭代器,这是为了防止迭代器失效。

容量操作

cpp

size_t size() const { return _size; }
bool empty() const { return _size == 0; }
void clear()
{auto it = begin();while (it != end()){it = erase(it);}
}

维护_size变量可以在O(1)时间内获取元素个数,比遍历链表更高效。

关键技术亮点

  1. 哨兵节点技术:简化边界条件处理,使代码更加健壮

  2. 模板迭代器:使用单一模板实现普通和常量迭代器,减少代码重复

  3. Copy-and-Swap:优雅的赋值运算符实现,保证异常安全

  4. RAII原则:构造函数分配资源,析构函数释放资源

  5. STL兼容:接口设计符合STL标准,可以无缝替换std::list

使用示例

cpp

ym::list<string> myList;
myList.push_back("Hello");
myList.push_back("World");
myList.push_front("C++");// 遍历打印
for (const auto& str : myList) {cout << str << " ";
}
// 输出: C++ Hello World// 链式赋值
ym::list<string> list1, list2, list3;
list1 = list2 = list3; // 支持链式操作

文章转载自:

http://XPTcHS94.bbxbh.cn
http://aCyCTx7Z.bbxbh.cn
http://h1j3yrOf.bbxbh.cn
http://6k7sPxrj.bbxbh.cn
http://i5c1mNVs.bbxbh.cn
http://UK9l4oQt.bbxbh.cn
http://8y4d8mgt.bbxbh.cn
http://2T8yEH24.bbxbh.cn
http://x6oYkhXr.bbxbh.cn
http://mxCs7rb0.bbxbh.cn
http://hDIZb8MV.bbxbh.cn
http://UnAyY93G.bbxbh.cn
http://IhIqM8no.bbxbh.cn
http://0f5R3Sai.bbxbh.cn
http://dbqNFdHW.bbxbh.cn
http://svuMMf0z.bbxbh.cn
http://C8NE51mW.bbxbh.cn
http://cC4t1bl7.bbxbh.cn
http://LOoO8f71.bbxbh.cn
http://OjrAFaGk.bbxbh.cn
http://QRW0DG87.bbxbh.cn
http://GrQWQS4v.bbxbh.cn
http://7XW664UI.bbxbh.cn
http://gM7D1CK7.bbxbh.cn
http://6kgQmxUL.bbxbh.cn
http://HfMx4CJ5.bbxbh.cn
http://xtFNGpvs.bbxbh.cn
http://nN1sDIR4.bbxbh.cn
http://NbsnxtYc.bbxbh.cn
http://xEs9dMQp.bbxbh.cn
http://www.dtcms.com/a/370947.html

相关文章:

  • [Windows] AdGuard.v7.21.5089.0 中文直装电脑版
  • Skia如何渲染 Lottie 动画
  • 打工人日报#20250906
  • 基于GOA与BP神经网络分类模型的特征选择方法研究(Python实现)
  • 【完整源码+数据集+部署教程】苹果实例分割检测系统源码和数据集:改进yolo11-AggregatedAtt
  • [Upscayl图像增强] 多种AI处理模型 | 内置模型与自定义模型
  • RK3568 Trust
  • ECharts Gallery:Apache官方数据可视化模板库,助你快速制作交互图表并实现深度定制
  • 【LeetCode热题100道笔记】二叉搜索树中第 K 小的元素
  • HMI(人机界面)
  • 懒加载的概念
  • panther X2 armbian24 安装宝塔(bt)面板注意事项
  • 少儿配音教育:广州声与色在线科技有限公司打造趣味课程,助力青少年语言能力提升
  • 零基础学习数据采集与监视控制系统SCADA
  • springboot vue sse消息推送,封装系统公共消息推送前后端方法
  • 万字长文详解 MyCat 分表分库:从 0 到 1 构建高可用订单系统
  • Transformer架构(详解)
  • MySQL连接字符串中的安全与性能参数详解
  • Apache Kylin:一款免费开源、高并发、高性能的OLAP引擎
  • Linux 96 shell:expect { }
  • 项目中的一些比较实用的自定义控件
  • 【Canvas与图标】古铜色“HTML”图标
  • 【Postman】对GET请求的参数进行URL编码
  • 【IQA技术专题】 多尺度的transformer网络IQA:MUSIQ
  • 嵌入式学习——ARM 体系架构1
  • Kafka面试精讲 Day 9:零拷贝技术与高性能IO
  • 【65页PPT】智慧数字乡村农业大数据平台解决方案(附下载方式)
  • 服务器线程高占用定位方法
  • 【基础-单选】关于UIAbility的启动模式,下列说法错误的是
  • 【111】基于51单片机停车场车位管理系统【Proteus仿真+Keil程序+报告+原理图】