STL--List 常用接口简单介绍:
1、底层原理:
-
1、list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
-
2、list的底层是双向循环链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指
-
针指向其前一个元素和后一个元素。
-
3、list与forward_list非常相似: 最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高
效。
-
4、与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率
更好。
-
5、与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list
的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间
-
开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可
-
能是一个重要的因素)
-
6、附上List文档链接:想了解更多,戳这里?
2、模块介绍:
list中的接口比较多,以下为list中一些常见的重要接口:
1>构造:
- list()------------------------------构造空的list
- list(size_type n, const value_type& val = value_type())------构造的list中包含n个值为val的元素
- list(const list& x)------------------拷贝构造函数
- list(InputIterator first,InputerIterator last)----------用[first,last)区间中的元素构造list
2、list iterator的使用:此处,大家可暂时将迭代器理解成一个指针,该指针指向list中的某个节点。
- begin() + end()----(正向迭代器)---返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器
- rbegin() + rend()----(反向迭代器)---返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的 reverse_iterator,即begin位置
3、list capacity
- empty()----------------检测list是否为空,是返回true,否返回false
- size()------------------返回list中有效节点的个数
4、list element access
- front()------------------返回list的第一个节点中值的引用
- back()------------------返回list的最后一个节点中值的引用
5、list modifiers
- 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中的有效元素
6、特别注意:⚠️List中迭代器失效问题
此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节 点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代 器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。
具体看代码。
3、代码实现:
//STL_List list的常用接口简单使用
#include<iostream>
using namespace std;
//list:带头节点的双向循环链表
#include<list>
#include<vector>
//list构造
void TestList1()
{
list<int> L1; //构造空的L1
list<int> L2(10,5); //L2中放10个值为5的元素
vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
list<int> L3(v.begin(), v.end()); //区间构造 vector 提供构造区间。
//[begin(),end()),左闭右开
list<int> L4(arr, arr + sizeof(arr) / sizeof(arr[0])); //区间构造 数组提供构造区间。
list<int> L5(L4); //拷贝构造
cout << L1.size() << endl;
//迭代器访问L2
//list<int>::iterator it = L2.begin(); //C++98 提供的办法
auto it = L2.begin(); //C++11 提供的办法
while (it != L2.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//范围for循环遍历L3 //C++11
for (auto e : L3)
{
cout << e << " ";
}
cout << endl;
cout << L4.front() << endl;
cout << L4.back() << endl;
//反向迭代器遍历L5
auto rit = L5.rbegin();
while (rit != L5.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
}
//List增删改查
void TestList2()
{
list<int> L;
L.push_back(1); //尾插 插入五个元素
L.push_back(2);
L.push_back(3);
L.push_back(4);
L.push_back(5);
cout << L.size() << endl;
L.push_front(0); //头插
cout << L.front() << endl;
L.pop_back(); //尾删
cout << L.back() << endl;
L.pop_front(); //头删
cout << L.front() << endl;
//1 2 3 4
//list<int>::iterator it = L.begin(); //C++98
auto it = L.begin(); //C++11 定义迭代器
it = find(L.begin(), L.end(), 2); //find()方法在区间内找第一个值为2的元素,返回值为该元素的迭代器
if (it != L.end()) //判断条件保证L不为空
{
L.insert(it, 9); //insert方法在it位置之前插入9
}
L.erase(it); //删除it位置元素,要注意:此时it的含义--〉it指向第一次找到的值为2的元素,因此这里会删除之前找到的元素2
cout << L.size() << endl;
//IsOdd(int data); 操作同上
}
//remove() , remove_if()
// 判断偶数操作
bool IsEven(int data)
{
if (0 == data % 2)
return true;
return false;
}
//判断奇数操作
bool IsOdd(int data)
{
if (0 == data % 2)
return true;
return false;
}
void TestList3()
{
list<int> L{ 1, 2, 3, 2, 2, 4, 2 };
for (auto e : L)
{
cout << e << " ";
}
cout << endl;
//删除所有的2
L.remove(2); //remove()方法为删除所有和所传值相同的元素
//1 3 4
cout << L.size() << endl;
//删除L中所有的偶数
L.remove_if(IsEven); //remove_if()方法为删除所有符合条件的元素,函数参数即为条件
//1 3
cout << L.size() << endl;
//L.remove_if(IsOdd); //删除L中所有的奇数
}
//unique()
void TestList4()
{
list<int> L{ 1, 2, 3, 4, 9, 2, 2, 4, 2 };
L.sort(); //排序
for (auto e : L)
{
cout << e << " ";
}
cout << endl;
//unique():去重,删掉重复的元素
//使用unique()前提是保证链表是有序的
L.unique();
auto it = L.begin();
while (it != L.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
//迭代器失效问题
//list中迭代器失效----〉迭代器指向的节点不存在
void TestList5()
{
list<int> L{ 1, 2, 3, 4 };
//list<int>::iterator it = L.begin(); //C++98
auto it = L.begin(); //C++11
L.erase(it);
//it迭代器失效,erase之后,it所指向的节点已经被删除了
//解决办法:重新给it赋值
it = L.begin();
while (it != L.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
int main()
{
//TestList1(); //list构造
//TestList2(); //List增删改查
//TestList3(); //remove() , remove_if()
//TestList4(); //unique()
TestList5(); //迭代器失效问题
return 0;
}