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

在这里插入图片描述

1.基本结构

vectorstring不同list需要:

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

一个类来连接这些节点

如下:

image-20241123225107228

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. 将节点连接到链表中

    • 通过头来找到尾节点

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

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

代码实现如下:

image-20241129193432050

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

image-20241123230917615

2.2 迭代器的实现

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

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

那我们该怎么办呢?

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

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

image-20241124152351264

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

这里实现有三种方式:

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

image-20241124151945805

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

image-20241124162049096

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

image-20241124210554334

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

image-20241124210519041

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

image-20241124210719549

image-20241124211851273

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

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

image-20241124212155380

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

这是为什么呢?

image-20241130100508115

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

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

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

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

image-20241130103737051

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

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

image-20241130112729716

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

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

4.任意位置的插入删除

1. 插入

实现比list简单一点

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

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

image-20241124155603177

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

image-20241124155729268

2. 删除

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

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

image-20241124160021807

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

image-20241130155325713

具体使用方法如下:

image-20241130155300071

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

image-20241124160144611

5.析构与拷贝构造

5.1 析构函数

我们现将析构函数写出来

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

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

image-20241130160117508

5.2 拷贝构造

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

image-20241130160419414

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

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

image-20241130160635714

5.3 赋值重载

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

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

image-20241130161713955

测试一下:

image-20241130161654567

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值