C++ 容器 list

21 篇文章 0 订阅
18 篇文章 0 订阅

在了解list容器之前,我们要知道双向链表是什么,不知道的可以看这一篇:数据结构之链表-CSDN博客,其中就讲了双向链表。

list

下面我会从list结构简单讲解,list的相关函数介绍及使用,list的简单实现来讲解list。

list的结构

list是封装的双向链表结构,因为独特的链式结构,所以在插入、删除效率上很高。具体结构分析看上面的博客有具体讲解。

list的函数

构造函数

构造函数里面牵扯了内存池的东西,这里我先不把它扯进来防止难以理解。后面单独出一期再讲(其实是我还没学内存池)

在每一个构造函数构造数据节点之前,会有一次同样的操作,就是构造header哨兵位节点。方便数据插入删除的操作。

默认构造函数

默认构造就是不构造数据节点,只是创建哨兵位节点。

带参构造

将这两种传参统一一下就是:

第一个n表示链表的长度,第二个表示链表每个节点的内容。

迭代器构造

不知道迭代器的可以看这一篇博客c++迭代器的介绍-CSDN博客

将一个容器的迭代器输入进去进行构造:

拷贝构造

拷贝构造就是用一个已经创建好的对象的值去创建一个新的对象:

初始化设定项列表构造

还不知道初始化设定项列表的,可以去看看这一篇博客:c++ 初始值设定项列表(initializer_list)-CSDN博客

右值引用构造

这个我先不讲,还没仔细的学。

析构函数

析构就是要将每一个节点包括哨兵位的内存释放掉。

operator=

operator=就是赋值操作,与拷贝不同在于赋值是给已经创建好的对象赋值。

迭代器相关函数

迭代器相关函数所有容器都是一样的,推荐大家直接去看这篇博客,看完后所有容器的迭代器函数都没问题了:c++迭代器的介绍-CSDN博客

capacity相关函数

empty函数就是判断是否为空,是返回true,反之返回false。

size函数返回链表的长度

max_size一般是返回size_t形式的-1(理论上我们的链表是可以十分长的,我们的堆区内存很大,但是我们size_t变量的返回最大就-1,这里为什么是-1要有点补码原码的知识才行)

element相关函数

front函数就是返回开头第一个节点的值的引用,让我们可以读取值,在非const的情况下我们还可以直接改变它的值。

back和front函数是一样的,只是返回的末尾引用

modify相关的函数

这些函数我们在上一个容器vactor里面基本都见过了,所以很好掌握:

第一个assign函数就是重新给链表值从而覆盖之前的内容:

这里支持的重赋值有迭代器、带参构造和初始化设定项列表三种。

第二个emplace_front和第三个push_front在功能上面是相同的,都是头插,但是前者在某一些情况下效率更高,这里不多介绍,我还没学。

pop_front就是头删

emplace_backpush_back也是同样的作用,用于尾插。

pop_back是用于尾插

emplaceinsert也是同理的,都是属于插入的

这里只讲insert:

这里就可以看成在某个节点前面使用了构造函数插入这些值。那么使用就和构造函数没什么不同,除了没有默认,毕竟默认不构造值。

erase就是删除节点或者区间

这里区间只能用迭代器来表示。

resize函数可以重新定义长度

如果是比原来短就直接删除多余的,如果是增长就是输入一个缺省值,不输入就是T()来进行构造。

clear函数就是清空链表,只留哨兵节点

operations相关函数

这里面有些函数是在list里面独有的

splice(连接),就是将两个链表链接在一起,但是有主体,是A链接给B函数B链接给A,假如B链接给A,那么B的相关内容就会给A,B就没有没有这些内容了。

这里看着有六个函数,其实可以简化成三个,不同的就是右值引用。所有三大块不同就在于后面的迭代器器,如果后面没有跟迭代器那么就是把x链表的所有内容连接过去,如果有一个迭代器,那么就是把这个地方的一个节点连接过去,如果是迭代器区间,那么就是将迭代器区间的东西连接过去。

remove就是查找val,如果和val相等的节点值就删除,有几个删几个。

remove_if函数

就是有条件的删除,删除的内容更宽泛:

这里我们可以传回调函数地址,或者传仿函数(不知道仿函数的可以看这一篇:C++ 仿函数-CSDN博客

例如下面:

unique

unique就是去重的操作,但是前提为这个链表是有序的

merge

merge就是进行归并操作,将两个链表合成一个按相关要求排序的链表。既然是归并那么就要保证它是有序的

sort

这个不用多说就是用归并来实现的排序,速度比std::sort要慢三四倍。

reverse

反转链表,不用多说

observer类函数

这个是和内存池相关的函数,内存池我单独出一篇讲(其实是还没学)

全局函数

支持逻辑运算操作

swap

这个swap比std::swap更加比配,所以在调用全局的swap时会优先匹配这个函数,然后实例化。防止使用std::swap出错。

list的实现

list主要的难点就是框架的搭建,几个函数的实现都很简单。所以我主要讲框架。

节点类封装

首先是双向链表的节点,因为list类会经常访问,所以我们可以将节点类用struct来封装:

迭代器封装

我们list的迭代器就不同于vector、string,因为list的内存不是连续的,所以不能像vector、string直接迭代器++或者--,需要用类封装iterator并用operator重载。

另外,我们的迭代器分为iterator和const_iterator等迭代器,那么我们是否要写两个类来分别实现呢?其实我们只要用类模版就行了:

list类封装

那些相关函数我就不实现了,都不是特别难。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值