list简单介绍
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190619143810118.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Nzc18wOTE2,size_16,color_FFFFFF,t_70)
看到英文不要慌,翻译在下面(O(∩_∩)O哈哈~):
- list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
- list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
- list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,以让其更简单高效。
- 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190610100750748.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Nzc18wOTE2,size_16,color_FFFFFF,t_70)
list的使用
构造函数
构造函数 | 接口说明 |
---|
list(); | 构造空的list |
list(size_type n, const value_type& val = value_type()); | 构造的list中包含n个值为val的元素 |
list(const list& x); | 拷贝构造函数 |
list(InputIteratot first, InputIterator last); | 用[first, last)区间中的元素构造list |
#include <iostream>
#include <list>
int main(){
std::list<int> l1;
std::list<int> l2(4, 100);
std::list<int> l3(l2);
std::list<int> l4(l3.begin(), l3.end());
for(auto e : l1){
std::cout << e << " ";
}
std::cout << std::endl;
for(auto e : l2){
std::cout << e << " ";
}
std::cout << std::endl;
for(auto e : l3){
std::cout << e << " ";
}
std::cout << std::endl;
for(auto e : l4){
std::cout << e << " ";
}
std::cout << std::endl;
return 0;
}
[sss@aliyun list]$ g++ constructor.cc -o constructor -std=c++11
[sss@aliyun list]$ ./constructor
100 100 100 100
100 100 100 100
100 100 100 100
迭代器
函数声明 | 接口说明 |
---|
begin() + end() | 返回第一个元素的迭代器 + 返回最后一个元素下一个位置的迭代器 |
rbegin() + rend() | 返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的reverse_iterator,即begin位置 |
注意:
- begin和end为正向迭代器,对迭代器进行++操作,迭代器向后移动。
- rbegin和rend为反向迭代器,对迭代器进行++操作,迭代器向前移动。
#include <iostream>
#include <list>
void ListDiaplsy(const std::list<int>& l){
std::list<int>::const_iterator cit = l.begin();
while(cit != l.end()){
std::cout << *cit << " ";
++cit;
}
std::cout << std::endl;
}
int main(){
std::list<int> l1;
l1.push_back(1);
l1.push_back(2);
l1.push_back(3);
std::list<int>::iterator it = l1.begin();
while(it != l1.end()){
std::cout << *it << " ";
++it;
}
std::cout << std::endl;
std::list<int>::reverse_iterator rit = l1.rbegin();
while(rit != l1.rend()){
std::cout << *rit << " ";
++rit;
}
std::cout << std::endl;
ListDiaplsy(l1);
return 0;
}
[sss@aliyun list]$ !g++
g++ iterator.cc -o iterator
[sss@aliyun list]$ ./iterator
1 2 3
3 2 1
1 2 3
容量相关接口
函数声明 | 接口说明 |
---|
bool empty(); | 检测list是否为空,是返回true,否则返回false |
size_t size(); | 返回list中有效结点的个数 |
#include <iostream>
#include <list>
int main(){
std::list<int> l1;
l1.push_back(1);
std::cout << l1.empty() << std::endl;
std::cout << l1.size() << std::endl;
return 0;
}
[sss@aliyun list]$ g++ capacity.cc -o capacity
[sss@aliyun list]$ ./capacity
0
1
元素相关接口
函数声明 | 接口说明 |
---|
front(); | 返回list的第一个节点中值的引用 |
back(); | 返回list的最后一个结点中值的引用 |
#include <iostream>
#include <list>
int main(){
std::list<int> l1;
l1.push_back(1);
l1.push_back(2);
std::cout << l1.front() << std::endl;
std::cout << l1.back() << std::endl;
return 0;
}
[sss@aliyun list]$ g++ element.cc -o element
[sss@aliyun list]$ ./element
1
2
修改操作
函数声明 | 接口说明 |
---|
void push_front( const T& value ); | 在list首元素前插入值为val的元素 |
void pop_front(); | 删除list中第一个元素 |
void push_back( const T& value ); | 在list尾部插入值为val的元素 |
void pop_back(); | 删除list中最后一个元素 |
iterator insert( iterator pos, const T& value ); | 在list pos位置中插入值为val的元素 |
iterator erase( iterator pos ); | 删除list pos位置的元素 |
void swap( list& other ); | 交换两个list的元素 |
void clear(); | 清空list中的有效元素 |
#include <iostream>
#include <list>
void PushPopTest(){
std::list<int> l1;
l1.push_back(1);
l1.push_back(2);
l1.push_back(3);
l1.push_front(10);
l1.push_front(20);
l1.push_front(30);
for(auto e : l1){
std::cout << e << " ";
}
std::cout << std::endl;
l1.pop_back();
l1.pop_front();
for(auto e : l1){
std::cout << e << " ";
}
std::cout << std::endl;
}
void InsertEraseTest(){
std::list<int> l1;
l1.insert(l1.begin(), 1);
for(auto e : l1){
std::cout << e << " ";
}
std::cout << std::endl;
l1.erase(l1.begin());
for(auto e : l1){
std::cout << e << " ";
}
std::cout << std::endl;
}
void SwapTest(){
std::list<int> l1;
l1.push_back(1);
std::list<int> l2;
l2.push_back(2);
l1.swap(l2);
std::cout << "l1: ";
for(auto e : l1){
std::cout << e << " ";
}
std::cout << std::endl;
std::cout << "l2: ";
for(auto e : l2){
std::cout << e << " ";
}
std::cout << std::endl;
}
void ClearTest(){
std::list<int> l1;
l1.push_back(1);
l1.push_back(2);
for(auto e : l1){
std::cout << e << " ";
}
std::cout << std::endl;
l1.clear();
for(auto e : l1){
std::cout << e << " ";
}
std::cout << std::endl;
}
int main(){
std::cout << "Push Pop: " << std::endl;
PushPopTest();
std::cout << std::endl;
std::cout << "Insert Erase: " << std::endl;
InsertEraseTest();
std::cout << std::endl;
std::cout << "Swap: " << std::endl;
SwapTest();
std::cout << std::endl;
std::cout << "Clear: " << std::endl;
ClearTest();
std::cout << std::endl;
return 0;
}
[sss@aliyun list]$ g++ modifiers.cc -o modifiers -std=c++11
[sss@aliyun list]$ ./modifiers
Push Pop:
30 20 10 1 2 3
20 10 1 2
Insert Erase:
1
Swap:
l1: 2
l2: 1
Clear:
1 2
迭代器失效
前面说过,迭代器失效即迭代器所指向的节点无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不是会导致list的迭代器失效,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受影响。
失效情况
#include <iostream>
#include <list>
int main(){
std::list<int> l1;
l1.push_back(1);
l1.push_back(2);
l1.push_back(3);
std::list<int>::iterator it = l1.begin();
while(it != l1.end()){
l1.erase(it);
++it;
}
for(auto e : l1){
std::cout << e << " ";
}
std::cout << std::endl;
return 0;
}
[sss@aliyun list]$ g++ invalid_iterator.cc -o invalid_iterator -std=c++11
[sss@aliyun list]$ ./invalid_iterator
Segmentation fault
修改后
#include <iostream>
#include <list>
int main(){
std::list<int> l1;
l1.push_back(1);
l1.push_back(2);
l1.push_back(3);
std::list<int>::iterator it = l1.begin();
while(it != l1.end()){
it = l1.erase(it);
++it;
}
for(auto e : l1){
std::cout << e << " ";
}
std::cout << std::endl;
return 0;
}
[sss@aliyun list]$ !g++
g++ invalid_iterator.cc -o invalid_iterator -std=c++11
[sss@aliyun list]$ ./invalid_iterator