其实现在在讲这些容器的时候,我们的重点已经不是它的接口都有什么,功能都是什么了,这些内容官网上都能查到,而且容器和容器之间接口的不同处很少,我在讲解的话也只是把官网上的东西截图下来复述一下。现在的重点其实都是容器的下半节,也就是容器的实现。
list容器是一个带头双向循环链表
1. 构造 析构 赋值重载
1.1 构造
官网资料:list::list - C++ Reference
C++98中的构造还是老几样,不用传参的默认构造,用n个val构造,用某段迭代区间构造,拷贝构造,不过C++11中的initializer_list构造我们也可以使用
1.2 析构
官网资料:list::~list - C++ Reference
1.3 赋值重载
官网资料:list::operator= - C++ Reference
C++98中只提供一种赋值方案,但是C++11标准中还可以用initializer_list赋值
2. 迭代器
begin和end没啥好说的,前面有r说明是reverse迭代器,也就是倒着的迭代器,前面载有c就是const迭代器const_iterator,不过这些我们都不常用,主要还是用begin和end
因为list是带头双向循环链表,因此它的迭代器于之前string或vector的随机迭代器不同,list的迭代器是双向迭代器
3.容量操作
之前提到过max_size返回容器目前的最大容量,不过这是一个相当鸡肋的功能
4. 访问容器内容
访问容器内容还是提供了front、back两个成员函数,但是并没有提供operator[ ]了,这是因为链表的数据不是像顺序表那样的数组模式,无法 [ ] 随机访问某个元素,如果硬要写重载也行,但是效率低下,就是每次访问都遍历一下链表。
也就是说,在链表中我们访问元素的方式完全变成了迭代器访问
5. 内容更改操作
assign重新赋值,不过这个成成员函数需要的参数和构造很像
push_front pop_front push_back pop_back,头插头删,尾插尾删,这些我们都很熟悉了
insert随机位置插入,erase随机位置删除
swap交换两个链表,resize reverse调整链表大小,clear清空链表
6. 更多特殊操作
6.1 splice 转移链表节点
官网资料:list::splice - C++ Reference
这个成员函数的功能就是将另一个链表 x 中的节点拿过来拼接进这个节点中。
通过参数很简单可以看出,可以选择拼接一整条链表,或者链表中的某个节点,或者链表中用迭代器化出来的某段。
6.2 remove 删除存储某元素的节点
官网资料:list::remove - C++ Reference
和另一个有关删除的成员函数erase不同,erase是通过迭代器指定删除某些位置。而remove通过节点中存储的数据判断是否删除该节点
6.3 unique 相邻相同元素只保留一个
官网资料:list::unique - C++ Reference
unique是将相邻的相同元素只保留第一个,我们暂时只用它的第一种重载。所以说当我们想让一个链表中的每种元素只出现一次,就要先给这个链表排序,然后再用unique,排序是为了让相同的元素聚集到一起,否则删不干净。
左边是链表没排序就unique,这样会保留下每组相同数据中的第一个数据。右边是链表sort之后再unique的效果,排序后相同的元素就都聚到一起了,那再删出来的效果就是每种数据都留下一个了。
6.4 sort 排序
官网资料:list::sort - C++ Reference
库函数中的sort要求传过去的迭代器必须是像vector或string那样的随机迭代器,而list的迭代器是双向迭代器,这种迭代器是不支持减法的,因此list不能使用标准库中的sort函数,因此list有特别供给自己使用的sort,也是默认排升序的效果,如果我们传一个greater<T>仿函数,就可以排降序。
但是链表排序的时间消耗比较大,如果将链表中的数据用迭代区间拷贝构造法弄到顺序表中再排序,排序所需时间是比直接在链表中排序少3倍。
6.5 merge 合并有序链表
官网资料:list::merge - C++ Reference
这个成员函数的功能就是将两个有序链表合并成一个有序链表,合并完后被合并的有序链表x就变成了空链表
6.6 reverse 逆置
官网资料:list::reverse - C++ Reference
逆置整个链表,直接调用一下就好