今天我们来进入到C++另一个容器list的学习
目录
一、list的介绍
二、list的使用
2.1 构造函数
2.2 迭代器函数接口
2.3 容量函数接口
2.4 元素访问函数接口
2.5 常用修改函数接口
2.6 常用操作函数接口
一、list的介绍
文档介绍:list - C++ Reference (cplusplus.com)
1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
2. list的底层是带头双向循环链表结构,双向链表中每个元素存储在互不相关的独立节点,在节点中通过指针指向其前一个元素和后一个元素。
3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代。
4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个不可忽略的缺陷)
二、list的使用
对于先前学习过string和vectot的我们来说,上手list轻轻松松,不过需注意的是list是基于链表实现的容器,所以就没有reserve这些关于内存分配的函数接口。
2.1 构造函数
构造函数(constructor) | 接口说明 |
---|---|
list (size_type n, const value_type& val = value_type()) | 构造的list中包含n个值为val的元素 |
list() | 构造空的list |
list (const list& x) | 拷贝构造函数 |
list (InputIterator first, InputIterator last) | 用[first, last)区间中的元素构造list,迭代器构造 |
2.2 迭代器函数接口
函数声明 | 接口说明 |
---|---|
begin | 返回第一个元素的迭代器 |
end | 返回最后一个元素下一个位置的迭代器 |
rbegin | 返回第一个元素的reverse_iterator,即end位置(注意返回的是反向迭代器) |
rend | 返回最后一个元素下一个位置的 reverse_iterator,即begin位置(注意返回的是反向迭代器) |
2.3 容量函数接口
函数声明 | 接口说明 |
---|---|
empty | 检测list是否为空,是返回true,否则返回false |
size | 返回list中有效节点的个数 |
2.4 元素访问函数接口
函数声明 | 接口说明 |
---|---|
front | 返回list的第一个节点中值的引用 |
back | 返回list的最后一个节点中值的引用 |
2.5 常用修改函数接口
函数声明 | 接口说明 |
---|---|
push_front | 在list首元素前插入值为val的元素 |
pop_front | 删除list中第一个元素 |
push_back | 在list尾部插入值为val的元素 |
pop_back | 删除list中最后一个元素 |
insert | 在list的position位置中插入值为val的元素 |
erase | 删除lis中position位置的元素 |
swap | 交换两个list中的元素 |
clear | 清空list中的有效元素 |
2.6 常用操作函数接口
函数声明 | 接口说明 |
---|---|
splice | 将元素从x剪切插入到list指定位置中 |
remove | 去除list中重复的值为val的节点 |
sort(不推荐使用) | 对list中的节点进行排序 |
在这里提醒一下sort函数的效率是很低的,如果想要对list中的值进行排序,我们可以先将list中的值拷贝到vector中,再对vector进行排序后最后再拷贝回list中:
#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
using namespace std;
int main()
{srand(time(0));list<int> L1;list<int> L2;int val;for (int i = 0; i < 10000000; ++i){val = rand() + i;L1.push_back(val);L2.push_back(val);}int begin1 = clock();//将将list中的值拷贝到vector中vector<int> V;for (auto a : L1){V.push_back(a);}//再对vector进行排序后最后再拷贝回list中sort(V.begin(), V.end());L1.clear();for (auto a : V){L1.push_back(a);}int end1 = clock();//直接使用list提供的sort来排序int begin2 = clock();L2.sort();int end2 = clock();cout << "vector sort:" << end1 - begin1 << endl;cout << "list sort:" << end2 - begin2 << endl;return 0;
}
release环境下运行结果:
我们可以看到即使将list中的值转移到了vector中进行排序但是效率还是比用list中提供的sort接口快很多。
本期博客到这里就结束了,下一期很快就和大家见面了~