目录
一、list的介绍
- list是一种可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
- list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立结点当中,在结点中通过指针指向其前一个元素和后一个元素。
- list与forward_list非常相似,最主要的不同在于forward_list是单链表,只能进行单方向迭代。
与其他容器相比,list通常在任意位置进行插入、删除元素的执行效率更高。 - list和forward_list最大的缺陷是不支持在任意位置的随机访问,其次,list还需要一些额外的空间,以保存每个结点之间的关联信息(对于存储的类型较小元素来说这可能是一个重要的因素)。
二、list的使用
list的定义方式
构造函数 | 接口说明 |
---|---|
list() | 构造空的list |
list (size_type n, const value_type& val = value_type()) | 构造的list中包含n个值为val的元素 |
list (const list& x) | 拷贝构造函数 |
list (InputIterator first, InputIterator last) | 用[first, last)区间中的元素构造list |
cpp
void test_list()
{
//构造int类型的空容器
list<int> lt1;
// 构造一个含有n个val的某类型容器
list<int> lt2(5, 2);
//拷贝构造某类型容器
list<int> lt3(lt2);
//使用迭代器拷贝构造某一段内容
string str("hello world");
list<char> lt4(str.begin(), str.end()); //构造string对象某段区间的复制品
//构造数组某段区间的复制品
int arr[] = { 1, 2, 3, 4, 5 };
list<int> lt5(arr, arr + sizeof(arr) / sizeof(int));
}
三、list的插入和删除
函数声明 | 接口说明 |
---|---|
push_back | 在list尾部插入值为val的元素 |
pop_back | 删除list中最后一个元素 |
push_front | 在list首元素前插入值为val的元素 |
pop_front | 删除list中第一个元素 |
insert | 在list position 位置中插入值为val的元素 |
erase | 删除list position位置的元素 |
push_back和pop_back
cpp
void test1_list()
{
//push_back()和pop_back(),两种循环都可以
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
auto it = lt.begin();
while (it != lt.end())
{
cout << *it << " "; //1 2 3 4
++it;
}
cout << endl;
lt.pop_back();
lt.pop_back();
for (auto e : lt)
{
cout << e << " "; //1 2
}
cout << endl;
}
push_front和pop_front
cpp
void test2_list()
{
//push_front和pop_front,通常用范围for方便一点
list<int> lt1;
lt1.push_front(1);
lt1.push_front(2);
lt1.push_front(3);
for (auto e : lt1)
{
cout << e << " "; //3 2 1
}
cout << endl;
lt1.pop_front();
for (auto e : lt1)
{
cout << e << " "; //2 1
}
cout << endl;
}
insert
- 在指定迭代器位置插入一个数。
- 在指定迭代器位置插入n个值为val的数。
- 在指定迭代器位置插入一段迭代器区间(左闭右开)。
cpp
void test3_list()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
//5前插入17
//v.insert(v.begin() + 5, 17); //顺序表的话迭代器开头+5就可以插入
auto it = lt.begin(); //链表,1.类似指针指到5前,2.插入
for (size_t i = 0; i < 5; i++)
{
++it;
}
lt.insert(it,17);
for (auto e : lt)
{
cout << e << " "; //1 2 3 4 5 17
}
cout << endl;
//在指定的数前插入,例如在4前插入100,使用find找到该数
it = find(lt.begin(), lt.end(), 4);
if (it != lt.end())
{
lt.insert(it, 100);
}
for (auto e : lt)
{
cout << e << " "; //1 2 3 100 4 5 17
}
cout << endl;
}
find函数是头文件"algorithm"当中的一个函数,该函数在指定迭代器区间(左闭右开)寻找指定值的位置,并返回该位置的迭代器。
cpp
template<class InputIterator, class T>
InputIterator find (InputIterator first, InputIterator last, const T& val)
{
while (first!=last) {
if (*first==val) return first;
++first;
}
return last;
}
erase
list当中的erase函数支持两种删除方式:
- 删除指定迭代器位置的元素。
- 删除指定迭代器区间(左闭右开)的所有元素。
cpp
void test4_list()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_back(6);
lt.push_back(7);
auto it = find(lt.begin(), lt.end(), 3);
lt.erase(it); //删除3
for (auto e : lt)
{
cout << e << " "; //1 2 4 5 6 7
}
cout << endl;
it = find(lt.begin(), lt.end(), 5);
lt.erase(it, lt.end()); //删除5后所有元素(左闭右开)
for (auto e : lt)
{
cout << e << " "; //1 2 4
}
cout << endl;
}
四、list的迭代器使用
函数声明 | 接口说明 |
---|---|
begin + end | 返回第一个元素的迭代器+返回最后一个有效元素下一个位置的迭代器 |
rbegin + rend | 返回第一个元素的reverse_iterator,即end位置,返回最后一个有效元素下一个位置的reverse_iterator,即begin位置 |
cpp
void test5_list()
{
//正向迭代器遍历容器
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
//list<int>::iterator it = lt.begin();
auto it = lt.begin();
while (it != lt.end())
{
cout << *it << " "; //1 2 3 4
++it;
}
cout << endl;
//反向迭代器遍历容器
list<int> lt1;
lt1.push_back(1);
lt1.push_back(2);
lt1.push_back(3);
lt1.push_back(4);
auto rit = lt1.rbegin();
while (rit != lt1.rend())
{
cout << *rit << " "; //4 3 2 1
++rit;
}
cout << endl;
}
五、list的元素获取
函数声明 | 接口说明 |
---|---|
front | 返回list的第一个节点中值的引用 |
back | 返回list的最后一个节点中值的引用 |
cpp
void test6_list()
{
list<int> lt;
lt.push_back(0);
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
cout << lt.front() << endl; //0
cout << lt.back() << endl; //4
}
六、list的大小控制
函数声明 | 接口说明 |
---|---|
size | 返回list中有效节点的个 |
resize | 1.当所给值大于当前的size时,将size扩大到该值,扩大的数据为第二个所给值,若未给出,则默认为容器所存储类型的默认构造函数所构造出来的值。2.当所给值小于当前的size时,将size缩小到该值。 |
empty | 检测list是否为空,是返回true,否则返回false |
clear | 清空list中的有效元素 |
cpp
void test7_list()
{
//size获取当前容器当中的元素个数
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
cout << lt.size() << endl; //4
//resize扩容(可赋值)或缩容
list<int> lt1(5, 2);
for (auto e : lt1)
{
cout << e << " "; //2 2 2 2 2
}
cout << endl;
lt1.resize(8, 5); //将size扩大为8,扩大的值为5
for (auto e : lt1)
{
cout << e << " "; //2 2 2 2 2 5 5 5
}
cout << endl;
lt1.resize(3); //将size缩小为3
for (auto e : lt1)
{
cout << e << " "; //2 2 2
}
cout << endl;
//empty判断是否为空,没元素返回1,有元素返回0
list<int> lt2;
cout << lt2.empty() << endl; //1
cout << lt1.empty() << endl; //0
//clear清空容器(size元素)
list<int> lt4(5, 2);
for (auto e : lt4)
{
cout << e << " "; //2 2 2 2 2
}
cout << endl;
cout << lt4.size() << endl; //5
lt.clear(); //清空容器
for (auto e : lt)
{
cout << e << " "; //(无数据)
}
cout << endl;
cout << lt.size() << endl; //0
}
七、list的操作函数
函数声明 | 接口说明 |
---|---|
sort | 将容器当中的数据默认排为升序 |
reverse | 将容器当中元素的位置进行逆置 |
splice | 用于两个list容器之间的拼接 |
remove | 用于删除容器当中特定值的元素 |
remove_if | 用于删除容器当中满足条件的元素 |
unique | 用于删除容器当中连续的重复元素 |
merge | 将一个有序list容器合并到另一个有序list容器当中,使得合并后的list容器任然有序。(类似于归并排序) |
assign | 将新内容分配给容器,替换其当前内容 |
swap | 交换两个容器的内容 |
sort和reverse
cpp
void test8_list()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(10);
lt.push_back(20);
for (auto e : lt)
{
cout << e << " "; //1 2 3 4 10 20
}
cout << endl;
lt.reverse();
for (auto e : lt)
{
cout << e << " "; //20 10 4 3 2 1
}
cout << endl;
}
merge
merge函数用于将一个有序list容器合并到另一个有序list容器当中,使得合并后的list容器任然有序。(类似于归并排序)
cpp
void test10_list()
{
list<int> lt;
lt.push_back(17);
lt.push_back(55);
lt.push_back(32);
list<int> lt1;
lt1.push_back(11);
lt1.push_back(3);
lt1.push_back(100);
lt.sort();
lt1.sort();
lt.merge(lt1); //将lt1合并到lt
for (auto e : lt)
{
cout << e << " "; //3 11 17 32 55 100
}
cout << endl;
}
remove
remove函数用于删除容器当中特定值的元素。
cpp
void test9_list()
{
int arr[] = { 12,65,32,11,22,11,3 };
list<int> mylist(arr, arr + sizeof(arr) / sizeof(int));
mylist.remove(11);
for (auto e : mylist)
{
cout << e << " "; //12 65 32 22 3
}
cout << endl;
}
remove_if
remove_if函数用于删除容器当中满足条件的元素
cpp
bool single_digit(const int& val)
{
return val < 10;
}
void test11_list()
{
list<int> lt;
lt.push_back(3);
lt.push_back(2);
lt.push_back(65);
lt.push_back(33);
lt.push_back(9);
lt.push_back(5);
lt.push_back(4);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl; //3 2 65 33 9 5 4
lt.remove_if(single_digit); //删除容器当中值小于10的元素
for (auto e : lt)
{
cout << e << " ";
}
cout << endl; //65 33
}
unique
unique函数用于删除容器当中连续的重复元素。
cpp
void test12_list()
{
list<int> lt;
lt.push_back(2);
lt.push_back(3);
lt.push_back(3);
lt.push_back(2);
lt.push_back(1);
lt.push_back(3);
lt.push_back(3);
for (auto e : lt)
{
cout << e << " ";
}
cout << endl; //2 3 3 2 1 3 3
lt.sort();
lt.unique(); //删除容器当中连续的重复元素
for (auto e : lt)
{
cout << e << " ";
}
cout << endl; //1 2 3
}
assign
assign函数用于将新内容分配给容器,替换其当前内容,新内容的赋予方式有两种:
- 将n个值为val的数据分配给容器。
- 将所给迭代器区间当中的内容分配给容器。
cpp
void test13_list()
{
list<char> lt(3, 's');
lt.assign(4, 'a'); //将新内容分配给容器,替换其当前内容
for (auto e : lt)
{
cout << e << " "; //a a a a
}
cout << endl;
string str("hello word");
lt.assign(str.begin(), str.end()); //将新内容分配给容器,替换其当前内容
for (auto e : lt)
{
cout << e << " "; //h e l l o w o r d
}
cout << endl;
}
swap
cpp
void test14_list()
{
list<int> lt1(5, 2);
list<int> lt2(2, 6);
lt1.swap(lt2); //交换两个容器的内容
for (auto e : lt1)
{
cout << e << " ";
}
cout << endl; //6 6
for (auto e : lt2)
{
cout << e << " ";
}
cout << endl; //2 2 2 2 2
}