目录
一、List容器概述
1.1 什么是list?
list
是C++标准模板库(STL)中的序列式容器,底层采用双向链表实现,支持在任意位置进行O(1)时间复杂度的插入和删除操作。与vector
的连续内存布局不同,list的每个元素存储在一个独立的节点中,节点之间通过指针相互连接。这种结构使得 list
在任意位置插入和删除元素时具有较高的效率,但不支持随机访问。
1.2 核心特点
高效插入和删除:可以在常数时间内完成任意位置的插入和删除操作。
双向迭代:支持正向和反向遍历。
不支持随机访问:无法通过索引直接访问元素。
额外空间开销:每个节点需要存储指向前驱和后继的指针,因此存储空间较大。
二、List的定义与初始化
list
的定义方式非常灵活,以下是几种常见的定义方法:
#include <list>
using namespace std;
int main()
{
// 方式一:创建空容器
list<int> lt1;
// 方式二:n个相同元素
list<int> lt2(5, 100); // 5个100
// 方式三:拷贝构造
list<int> lt3(lt2);
// 方式四:迭代器范围初始化
string str = "hello";
list<char> lt4(str.begin(), str.end());
// 方式五:数组初始化
int arr[] = { 1,3,5,7,9 };
list<int> lt5(arr, arr + 5);
return 0;
}
三、List 的基本操作
3.1 插入操作
🌵头插和尾插
-
头插:
push_front
将元素插入到容器的头部。 -
尾插:
push_back
将元素插入到容器的尾部。
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lt;
lt.push_front(0);
lt.push_front(1);
lt.push_front(2);
for (auto e : lt)
{
cout << e << " "; // 输出:2 1 0
}
cout << endl;
lt.push_back(3);
for (auto e : lt)
{
cout << e << " "; // 输出:2 1 0 3
}
cout << endl;
return 0;
}
🌵指定位置插入
-
单个值:在指定迭代器位置插入一个值。
-
多个值:在指定迭代器位置插入多个相同值。
-
区间:在指定迭代器位置插入一个区间的内容。
#include <iostream>
#include <algorithm>
#include <vector>
#include <list>
using namespace std;
int main()
{
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
auto pos = find(lt.begin(), lt.end(), 2);
lt.insert(pos, 9); // 插入单个值
for (auto e : lt)
{
cout << e << " "; // 输出:1 9 2 3
}
cout << endl;
pos = find(lt.begin(), lt.end(), 3);
lt.insert(pos, 2, 8); // 插入多个值
for (auto e : lt)
{
cout << e << " "; // 输出:1 9 2 8 8 3
}
cout << endl;
vector<int> v(2, 7);
pos = find(lt.begin(), lt.end(), 1);
lt.insert(pos, v.begin(), v.end()); // 插入区间
for (auto e : lt)
{
cout << e << " "; // 输出:7 7 1 9 2 8 8 3
}
cout << endl;
return 0;
}
3.2 删除操作
🍋头删和尾删
-
头删:
pop_front
删除容器头部的元素。 -
尾删:
pop_back
删除容器尾部的元素。
lt.pop_front(); // 删除头部元素
for (auto e : lt)
{
cout << e << " "; // 输出:7 1 9 2 8 8 3
}
cout << endl;
lt.pop_back(); // 删除尾部元素
for (auto e : lt)
{
cout << e << " "; // 输出:7 1 9 2 8 8
}
cout << endl;
🍋指定位置删除
-
单个元素:删除指定迭代器位置的元素。
-
区间:删除指定迭代器区间内的所有元素。
pos = find(lt.begin(), lt.end(), 9);
lt.erase(pos); // 删除单个元素
for (auto e : lt)
{
cout << e << " "; // 输出:7 1 2 8 8
}
cout << endl;
pos = find(lt.begin(), lt.end(), 8);
lt.erase(pos, lt.end()); // 删除区间
for (auto e : lt)
{
cout << e << " "; // 输出:7 1 2
}
cout << endl;
四、List 的迭代器使用
4.1 正向迭代器
通过 begin
和 end
获取正向迭代器,用于正向遍历容器。
cout << "Forward iteration: ";
//list<int>::iterator it = lt.begin();
auto it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
4.2 反向迭代器
通过 rbegin
和 rend
获取反向迭代器,用于反向遍历容器。
cout << "Reverse iteration: ";
//list<int>::iterator rit = lt.rbegin();
auto rit = lt.rbegin();
while (rit != lt.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
五、List 的元素访问
5.1 获取首尾元素
-
首元素:
front()
返回第一个元素。 -
尾元素:
back()
返回最后一个元素。
cout << "First element: " << lt.front() << endl; // 输出:7
cout << "Last element: " << lt.back() << endl; // 输出:2
六、List 的大小控制
6.1 获取和调整大小
-
获取大小:
size()
返回容器中元素的数量。 -
调整大小:
resize()
用于调整容器大小。 -
判断是否为空:
empty()
判断容器是否为空。 -
清空容器:
clear()
清空容器。
// 获取大小
cout << "Size: " << lt.size() << endl; // 输出:3
// 调整大小
lt.resize(5, 5); // 扩大到 5 个元素,新增元素为 5
for (auto e : lt)
{
cout << e << " "; // 输出:7 1 2 5 5
}
cout << endl;
// 判断是否为空
cout << "Is empty: " << lt.empty() << endl; // 输出:0
// 清空容器
lt.clear();
cout << "Size after clear: " << lt.size() << endl; // 输出:0
七、List 的排序与拼接
7.1 排序操作
sort
函数对容器中的元素进行排序,默认为升序。
lt.push_back(4);
lt.push_back(7);
lt.push_back(3);
lt.sort(); // 排序
for (auto e : lt)
{
cout << e << " "; // 输出:3 4 7
}
cout << endl;
7.2 拼接操作
splice
用于将一个 list
的内容拼接到另一个 list
中。
-
拼接整个容器:将整个容器拼接到另一个容器的指定位置。
-
拼接单个元素:将单个元素拼接到另一个容器的指定位置。
-
拼接区间:将指定区间的元素拼接到另一个容器的指定位置。
// 拼接整个容器
list<int> lt1(4, 2);
list<int> lt2(4, 6);
lt1.splice(lt1.begin(), lt2);
for (auto e : lt1)
{
cout << e << " "; // 输出:6 6 6 6 2 2 2 2
}
cout << endl;
// 拼接单个元素
list<int> lt3(4, 2);
list<int> lt4(4, 6);
lt3.splice(lt3.begin(), lt4, lt4.begin());
for (auto e : lt3)
{
cout << e << " "; // 输出:6 2 2 2 2
}
cout << endl;
// 拼接区间
list<int> lt5(4, 2);
list<int> lt6(4, 6);
lt5.splice(lt5.begin(), lt6, lt6.begin(), lt6.end());
for (auto e : lt5)
{
cout << e << " "; // 输出:6 6 6 6 2 2 2 2
}
cout << endl;
八、List 的删除与去重
8.1 删除操作
-
删除特定值:
remove()
删除容器中所有特定值的元素。 -
删除满足条件的元素:
remove_if()
删除容器中满足条件的元素。
lt.push_back(1);
lt.push_back(3);
lt.push_back(3);
lt.push_back(2);
lt.remove(3); // 删除值为 3 的元素
for (auto e : lt)
{
cout << e << " "; // 输出:1 2
}
bool is_even(int val)
{
return val % 2 == 0;
}
lt.remove_if(is_even); // 删除偶数
for (auto e : lt)
{
cout << e << " "; // 输出:1
}
8.2 去重操作
unique
删除容器中连续的重复元素。
lt.push_back(1);
lt.push_back(2);
lt.push_back(2);
lt.push_back(3);
lt.push_back(3);
lt.push_back(3);
lt.sort(); // 先排序
lt.unique(); // 删除连续重复元素
for (auto e : lt)
{
cout << e << " "; // 输出:1 2 3
}
cout << endl;
九、List 的合并与反转
9.1 合并操作
merge
将一个有序 list
合并到另一个有序 list
中,结果仍保持有序。
list<int> lt1;
lt1.push_back(3);
lt1.push_back(1);
lt1.push_back(4);
lt1.sort(); // 排序 lt1
list<int> lt2;
lt2.push_back(6);
lt2.push_back(2);
lt2.push_back(5);
lt2.sort(); // 排序 lt2
lt1.merge(lt2); // 合并 lt2 到 lt1
for (auto e : lt1)
{
cout << e << " "; // 输出:1 2 3 4 5 6
}
cout << endl;
9.2 反转操作
reverse
将容器中的元素顺序反转。
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.reverse(); // 反转
for (auto e : lt)
{
cout << e << " "; // 输出:4 3 2 1
}
cout << endl;
十、List 的赋值与交换
10.1 赋值操作
assign
用于将新内容分配给容器,替换其当前内容。
-
赋值固定数量的值:
assign(n, val)
。 -
赋值区间内容:
assign(first, last)
。
lt.assign(3, 5); // 赋值 3 个 5
for (auto e : lt)
{
cout << e << " "; // 输出:5 5 5
}
cout << endl;
string s("hello");
lt.assign(s.begin(), s.end()); // 赋值字符串内容
for (auto e : lt)
{
cout << e << " "; // 输出:h e l l o
}
cout << endl;
10.2 交换操作
swap
用于交换两个容器的内容。
list<int> lt1(4, 2);
list<int> lt2(4, 6);
lt1.swap(lt2); // 交换内容
cout << "lt1: ";
for (auto e : lt1)
{
cout << e << " "; // 输出:6 6 6 6
}
cout << endl;
cout << "lt2: ";
for (auto e : lt2)
{
cout << e << " "; // 输出:2 2 2 2
}
cout << endl;