C++基础:list的底层实现

文章目录

1.基本结构

与vector和string不同list需要:

一个类来放入数据和指针也就是节点

一个类来连接这些节点

如下:

cpp 复制代码
template <class T>
class list_node
{
	T _data;
	list_node<T>* _next;//指向下一个节点
	list_node<T>* _prev;//指向前一个节点
};

template<class T>
class list
{
	typedef list_node<T> Node;
public:
	list()
	{
		_head = new Node;//没有内存池直接new一下即可
		_head->_next = _head;
		_head->_prev = _head;
	}
private:
	Node* _head;
};

2.迭代器的实现

2.1 尾插的实现

在写迭代器之前需要现将数据插入到链表中

那么尾插函数如何实现呢?

  1. 先来创建一个节点

  2. 将节点连接到链表中

    • 通过头来找到尾节点

    • 将尾节点和插入的节点连接起来

    • 再将最后一个尾节点和头相连,成为新的尾节点

代码实现如下:

当然我们还可以加一个size来记录我们链表的长度:

2.2 迭代器的实现

这里有一个和之前最大的区别就是:
之前无论是vector还是string都可以直接通过解引用或++来直接拿到我们想要的值和到达下一个位置

但是我们对list的节点解引用或++就拿不到我们想要的值和到达下一个节点

那我们该怎么办呢?

我们可以将*和++等操作符进行重载来拿到我们想要的内容

在将要重载的内容封装成一个类:

写完后我们就可以来完成begin和end的返回了

这里实现有三种方式:

  1. 创建一个类进行返回
  2. 用匿名对象进行返回
  3. 用隐式类型转换返回

再将后置++也完成出来:

但是这是如果出现链表是存放的是结构体就会出问题:

其原因仍然是直接解引用无法直接取到值:

我们可以重载一个->来完成进行AA结构体进行重载

这里的使用了特殊处理,应该使用两个->才合理,但是为了美观省略了一个

3.打印函数(模版复用实例化)

但是这里会有些问题,在函数外面写的范围for支持,而函数内的范围for不支持了

这是为什么呢?

原因就是这里是const容器,所以要const迭代器

要注意这两个迭代器的区别:

const_iterator 迭代器指向的内容不能修改(本身无法进行++)
const iterator 迭代器本身不能修改

这里要实现const_iterator就要将原有的iterator复制一份,后将其中部分进行修改:

但是这样实现代码就显得重复度很高了,能不能直降返回的那部分替换掉呢?

这里可以通过定义多个模版来实现这一功能:

这样我们只需要在调用的时候将要返回的参数写下来就能返回我们想要的迭代器

当然也可以用typedef进行重命名来更加方便实现

4.任意位置的插入删除

1. 插入

实现比list简单一点

先通过Node*找到插入的位置后

将将节点的链接方式改变一下就行了

当尾插写完后我们的其他插入方式就可以直接进行调用了

2. 删除

也是通过Node*找到删除节点的下一个节点的位置和前一个节点位置

将节点删除后将这两个节点相连即可:

当然为了放在删除后迭代器失效,我们可以再删除后返回下一个节点的位置

具体使用方法如下:

同理头删和尾删也可以直接调用erase

5.析构与拷贝构造

5.1 析构函数

我们现将析构函数写出来

这里需要现将所有节点全部删除后再将头节点删掉

我们可以现将清空函数分离开来,方便后续使用

5.2 拷贝构造

而拷贝构造就更加简单了,直接调用循环遍历进行尾插即可:

但是push_back就要有list的头节点,所以要进行初始化

我们可以将初始化封装成函数进行调用:

5.3 赋值重载

这里我们呢直接用新写法进行交换就行

注意:赋值重载函数不要传引用,否则就成为了真交换了

测试一下:

相关推荐
某不知名網友5 分钟前
ROS2进阶:服务通信、自定义SRV接口、参数服务器与基于服务的参数通信详解
java·开发语言·microsoft
傲世仙尊15 分钟前
string增删查改-insert-erase-replace与find加substr组合技
c++
java_nnnn19 分钟前
LeetCode刷题滑动窗口(水果成篮+找到字符串中所有字母的异位词)Java
java·开发语言·leetcode
qetfw25 分钟前
Bash 字符串处理:参数展开、序列与脚本执行方式
linux·开发语言·chrome·bash
小羊没烦恼!28 分钟前
异步编程:线程概述及使用
java·开发语言·mysql·算法·c#
学Linux的语莫1 小时前
python中类的常见写法
开发语言·python·状态模式
需要8261 小时前
容器化 Java:镜像瘦身与 JVM 容器感知(cgroup)
java·开发语言·jvm
dyxal1 小时前
A2A 协议 v1.0 完全指南:方法名、Agent Card、三种绑定与 FastAPI 实战
开发语言·qt·fastapi
譕痕1 小时前
Rabbit 实例
java·开发语言·java-rabbitmq
综合简报2 小时前
黑五海外发稿投给谁?三类海外媒体发稿渠道的分工
开发语言·php·媒体