赞
踩

1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素和后一个元素。
3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高 效。
4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率 更好。
5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list 的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间 开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这 可能是一个重要的因素)
list中的接口比较多,此处类似,只需要掌握如何正确的使用,然后再去深入研究背后的原理,已达到可扩展 的能力。以下为list中一些常见的重要接口。
| 构造函数( (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 |
- // list的构造
- void TestList1()
- {
- list<int> l1; // 构造空的l1
- list<int> l2(4, 100); // l2中放4个值为100的元素
- list<int> l3(l2.begin(), l2.end()); // 用l2的[begin(), end())左闭右开的区间构造l3
- list<int> l4(l3); // 用l3拷贝构造l4
-
- // 以数组为迭代器区间构造l5
- int array[] = { 16,2,77,29 };
- list<int> l5(array, array + sizeof(array) / sizeof(int));
-
- // 列表格式初始化C++11
- list<int> l6{ 1,2,3,4,5 };
-
- // 用迭代器方式打印l5中的元素
- list<int>::iterator it = l5.begin();
- while (it != l5.end())
- {
- cout << *it << " ";
- ++it;
- }
- cout << endl;
-
- // C++11范围for的方式遍历
- for (auto& e : l5)
- cout << e << " ";
-
- cout << endl;
- }

此处,可暂时将迭代器理解成一个指针,该指针指向list中的某个节点。
| 函数声明 | 接口说明 |
| begin + end | 返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器 |
| rbegin + rend | 返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的 reverse_iterator,即begin位置 |
【注意】
- 1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
- 2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动
- // list迭代器的使用
- // 注意:遍历链表只能用迭代器和范围for
- void PrintList(const list<int>& l)
- {
- // 注意这里调用的是list的 begin() const,返回list的const_iterator对象
- for (list<int>::const_iterator it = l.begin(); it != l.end(); ++it)
- {
- cout << *it << " ";
- // *it = 10; 编译不通过
- }
-
- cout << endl;
- }
-
- void TestList2()
- {
- int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
- list<int> l(array, array + sizeof(array) / sizeof(array[0]));
- // 使用正向迭代器正向list中的元素
- // list<int>::iterator it = l.begin(); // C++98中语法
- auto it = l.begin(); // C++11之后推荐写法
- while (it != l.end())
- {
- cout << *it << " ";
- ++it;
- }
- cout << endl;
-
- // 使用反向迭代器逆向打印list中的元素
- // list<int>::reverse_iterator rit = l.rbegin();
- auto rit = l.rbegin();
- while (rit != l.rend())
- {
- cout << *rit << " ";
- ++rit;
- }
- cout << endl;
- }

| 函数声明 | 接口说明 |
| push_front | 在list首元素前插入值为val的元素 |
| pop_front | 删除list中第一个元素 |
| push_back | 在list尾部插入值为val的元素 |
| pop_back | 删除list中最后一个元素 |
| insert | 在list position 位置中插入值为val的元素 |
| erase | 删除list position位置的元素 |
| swap | 交换两个list中的元素 |
| clear | 清空list中的有效元素 |
- // list插入和删除
- // push_back/pop_back/push_front/pop_front
- void TestList3()
- {
- int array[] = { 1, 2, 3 };
- list<int> L(array, array + sizeof(array) / sizeof(array[0]));
-
- // 在list的尾部插入4,头部插入0
- L.push_back(4);
- L.push_front(0);
- PrintList(L);
-
- // 删除list尾部节点和头部节点
- L.pop_back();
- L.pop_front();
- PrintList(L);
- }
-
- // insert /erase
- void TestList4()
- {
- int array1[] = { 1, 2, 3 };
- list<int> L(array1, array1 + sizeof(array1) / sizeof(array1[0]));
-
- // 获取链表中第二个节点
- auto pos = ++L.begin();
- cout << *pos << endl;
-
- // 在pos前插入值为4的元素
- L.insert(pos, 4);
- PrintList(L);
-
- // 在pos前插入5个值为5的元素
- L.insert(pos, 5, 5);
- PrintList(L);
-
- // 在pos前插入[v.begin(), v.end)区间中的元素
- vector<int> v{ 7, 8, 9 };
- L.insert(pos, v.begin(), v.end());
- PrintList(L);
-
- // 删除pos位置上的元素
- L.erase(pos);
- PrintList(L);
-
- // 删除list中[begin, end)区间中的元素,即删除list中的所有元素
- L.erase(L.begin(), L.end());
- PrintList(L);
- }
-
- // resize/swap/clear
- void TestList5()
- {
- // 用数组来构造list
- int array1[] = { 1, 2, 3 };
- list<int> l1(array1, array1 + sizeof(array1) / sizeof(array1[0]));
- PrintList(l1);
-
- // 交换l1和l2中的元素
- list<int> l2;
- l1.swap(l2);
- PrintList(l1);
- PrintList(l2);
-
- // 将l2中的元素清空
- l2.clear();
- cout << l2.size() << endl;
- }

| 函数声明 | 接口说明 |
| 从一个列表转移元素到另一个列表 | |
| 移除具有特定值的元素 | |
| 移除重复的数值 | |
| 合并排序过的列表 | |
| 对容器中的元素进行排序 | |
| 颠倒元素的顺序 |
- int main()
- {
- list<int> lt;
- lt.push_back(1);
- lt.push_back(2);
- lt.push_back(3);
- lt.push_back(4);
- lt.push_back(5);
-
-
- list<int>::iterator it = lt.begin();
- //while (it < lt.begin())
- //这里不能使用 < ,因为不能保证前一个节点比后一个大节点
- //链表间没有大小关系
- // < 只适用于底层物理空间连续:string,vector
- while (it != lt.end())
- {
- cout << *it << " ";
- ++it;
- }
- cout << endl;
-
- //逆置链表
- lt.reverse();
- for (auto e : lt)
- {
- cout << e << " ";
- }
- cout << endl;
-
- //归并链表
- //归并的前提:要求两个链表都有序
- list<int> lt1;
- lt1.push_back(1);
- lt1.push_back(2);
- lt1.push_front(1);
- // lt和lt1链表排序
- lt.sort();
- lt1.sort();
- lt.merge(lt1);
- for (auto e : lt)
- {
- cout << e << " ";
- }
- cout << endl;
-
- //链表去重 - 要求 - 链表有序/重复元素相邻
- lt.unique();
- for (auto e : lt)
- {
- cout << e << " ";
- }
- cout << endl;
-
- //链表排序
- lt.sort();
- for (auto e : lt)
- {
- cout << e << " ";
- }
- cout << endl;
- //这里提一个问题,能不能使用算法库的sort
- //这里为什么要单独提供一个链表的sort
- /*sort(lt.begin(), lt.end());
- for (auto e : lt)
- {
- cout << e << " ";
- }
- cout << endl;*/
- //error:_Sort_unchecked(_UFirst, _ULast, _ULast - _UFirst, _Pass_fn(_Pred));
- //算法库实现的sort是两个迭代器相减,list物理空间不连续,不支持相减
-
- //erase:删除pos位置的值
- //remove:根据值找pos位置+删除pos位置的值
- lt.remove(4);
- for (auto e : lt)
- {
- cout << e << " ";
- }
- cout << endl;
-
- //链表转移 - 节点转移
- list<int> mylist1, mylist2;
- list<int>::iterator it;
-
- // set some initial values:
- for (int i = 1; i <= 4; ++i)
- mylist1.push_back(i); // mylist1: 1 2 3 4
-
- for (int i = 1; i <= 3; ++i)
- mylist2.push_back(i * 10);// mylist2: 10 20 30
-
- it = mylist1.begin();
- ++it; // points to 2
-
- mylist1.splice(it, mylist2); // mylist1: 1 10 20 30 2 3 4
- // mylist2 (empty)
-
- //LRU,2最近被使用到 - 最少使用次数
- lt.splice(lt.end(), lt, find(lt.begin(), lt.end(), 2));
- for (auto e : lt)
- {
- cout << e << " ";
- }
- cout << endl;
- return 0;
- }

- 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
- 2. list的底层是带头双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
- 3. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
- 4. 与其他序列式容器相比,list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。