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

文章目录

1.基本结构

vectorstring不同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 赋值重载

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

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

测试一下:

相关推荐
Quantum&Coder5 分钟前
MATLAB语言的数据库交互
开发语言·后端·golang
网络空间站7 分钟前
MATLAB语言的软件工程
开发语言·后端·golang
C++小厨神11 分钟前
Rust语言的循环实现
开发语言·后端·golang
数维学长98620 分钟前
C++ STL 中的 `unordered_map` 和 `unordered_set` 总结
c++·算法·哈希算法
感谢地心引力21 分钟前
【MATLAB】绘制投资组合的有效前沿
开发语言·matlab·金融·股票·有效前沿
旧物有情21 分钟前
蓝桥杯历届真题--#好数,简单模拟(C++,Java)
java·c++·蓝桥杯
xianwu54324 分钟前
反向代理模块。
linux·开发语言·网络·c++·git
智驾1 小时前
SOLID原则学习,里氏替换原则
c++·里氏替换原则·solid
前端啊龙1 小时前
eslint.config.js和.eslintrc.js有什么区别
开发语言·前端·javascript
BinaryBardC1 小时前
R语言的软件工程
开发语言·后端·golang