目录
[1.定义 list 对象](#1.定义 list 对象)
[二、向 list 对象中添加元素](#二、向 list 对象中添加元素)
[三、list 常用迭代器](#三、list 常用迭代器)
[四、list 常用运算符](#四、list 常用运算符)
[五、list 常用成员函数](#五、list 常用成员函数)
[1.empty 成员函数](#1.empty 成员函数)
[2.size 成员函数](#2.size 成员函数)
[3.front 成员函数](#3.front 成员函数)
[4.push_front 成员函数](#4.push_front 成员函数)
[5.pop_front 成员函数](#5.pop_front 成员函数)
[6.back 成员函数](#6.back 成员函数)
[7.push_back 成员函数](#7.push_back 成员函数)
[8.pop_back 成员函数](#8.pop_back 成员函数)
[9.insert 成员函数](#9.insert 成员函数)
[10.erase 成员函数](#10.erase 成员函数)
[11.swap 成员函数](#11.swap 成员函数)
[12.clear 成员函数](#12.clear 成员函数)
[六、list 特有成员函数](#六、list 特有成员函数)
[1.merge 特有成员函数](#1.merge 特有成员函数)
[2.remove 特有成员函数](#2.remove 特有成员函数)
[3.remove_if 特有成员函数](#3.remove_if 特有成员函数)
[4.reverse 特有成员函数](#4.reverse 特有成员函数)
[5.sort 特有成员函数](#5.sort 特有成员函数)
[6.splice 特有成员函数](#6.splice 特有成员函数)
[7.unique 特有成员函数](#7.unique 特有成员函数)
[练习 1:list 基本操作](#练习 1:list 基本操作)
[练习 2:使用 list 特有成员函数](#练习 2:使用 list 特有成员函数)
[练习 3:使用 list 实现一个简单的链表](#练习 3:使用 list 实现一个简单的链表)
前言
STL中的list是一个双向循环链表,如下图所示:

第一个参数是任何数据类型,第二个参数可有可无。

list对象自带两个指针,一个指向第一个元素,另一个指向最后一个元素。
因此list在如下几个主要方面与array、 vector 或deque不同:
●list不支持随机访问,如果你要访问第5个元素,就得顺着链表逐一遍历前 4个元素。所以,在 list中随机访问任意元素是很缓慢的。然而访问第一个和最后一个元素的速度很快。
●任何位置(不只两端)插入和删除 都非常快,在常量时间内完成,因为无须移动其他元素。只需要进行一些指针操作。
list提供的比较好用的函数:
●list提供front,push_front,pop_front和back,push_back,pop_back等函数
●由于不支持随机访问,list即不支持下标操作也不支持at函数。
●list提供不少特殊成员函数,专门用于移动和删除元素,和同名的STL通用算法相比,这些函数执行起来更快速,优先使用list自己提供的算法。
一、定义及初始化
list 是 C++ 标准库中的一个双向链表容器,定义在 <list> 头文件中,位于 std 命名空间内。它支持在任意位置高效地插入和删除元素,但不支持随机访问。
使用list时必须先包含头文件<list>:
cpp
#include <list>
1.定义 list 对象
cpp
#include <list>
// 定义一个存储 int 类型的 list
std::list<int> lst;
// 定义一个存储 std::string 类型的 list
std::list<std::string> strLst;
2.初始化方式
-
默认初始化:创建一个空 list
cppstd::list<int> lst; // 空 list -
列表初始化:
cppstd::list<int> lst = {1, 2, 3, 4, 5}; std::list<int> lst2{1, 2, 3, 4, 5}; // 与上面等价 -
指定元素个数和初始值:
cppstd::list<int> lst(5, 10); // 包含 5 个元素,每个元素值为 10 -
使用另一个 list 初始化:
cppstd::list<int> lst1 = {1, 2, 3, 4, 5}; std::list<int> lst2 = lst1; // 拷贝初始化 std::list<int> lst3(lst1); // 拷贝构造 -
使用迭代器范围初始化:
cppstd::list<int> lst1 = {1, 2, 3, 4, 5}; std::list<int> lst2(lst1.begin(), lst1.end()); // 包含 lst1 的所有元素 // 从其他容器初始化 std::vector<int> vec = {6, 7, 8, 9, 10}; std::list<int> lst3(vec.begin(), vec.end()); // 包含 vec 的所有元素
二、向 list 对象中添加元素
list 支持在任意位置高效地添加元素,尤其是在两端和已知位置。
1.在前端添加元素
-
push_front 成员函数:
- 功能:在 list 前端添加一个元素
- 参数:要添加的元素值
- 返回值:无
cppstd::list<int> lst = {2, 3, 4}; lst.push_front(1); // lst 现在包含 {1, 2, 3, 4} -
emplace_front 成员函数(C++11):
- 功能:在 list 前端直接构造一个元素
- 参数:构造元素所需的参数
- 返回值:无
- 优点:避免了额外的拷贝或移动操作,比 push_front 更高效
cppstd::list<std::pair<int, std::string>> lst; lst.emplace_front(1, "one"); // 直接在前端构造 pair 对象 lst.push_front({2, "two"}); // 先构造临时 pair 对象,再移动到前端
2.在后端添加元素
-
push_back 成员函数:
- 功能:在 list 后端添加一个元素
- 参数:要添加的元素值
- 返回值:无
cppstd::list<int> lst = {1, 2, 3}; lst.push_back(4); // lst 现在包含 {1, 2, 3, 4} lst.push_back(5); // lst 现在包含 {1, 2, 3, 4, 5} -
emplace_back 成员函数(C++11):
- 功能:在 list 后端直接构造一个元素
- 参数:构造元素所需的参数
- 返回值:无
- 优点:避免了额外的拷贝或移动操作,比 push_back 更高效
cppstd::list<std::pair<int, std::string>> lst; lst.emplace_back(1, "one"); // 直接在后端构造 pair 对象 lst.push_back({2, "two"}); // 先构造临时 pair 对象,再移动到后端
3.在中间插入元素
-
insert 成员函数:
- 功能:在指定位置插入元素
- 参数:
- 版本 1:
pos, value- 在迭代器 pos 前插入 value - 版本 2:
pos, count, value- 在迭代器 pos 前插入 count 个 value - 版本 3:
pos, first, last- 在迭代器 pos 前插入迭代器范围 [first, last) 中的元素
- 版本 1:
- 返回值:指向新插入的第一个元素的迭代器
- 说明:在 list 中插入元素的效率很高,因为只需要修改指针,不需要移动元素
cppstd::list<int> lst = {1, 2, 4, 5}; // 在位置 2 前插入元素 3 auto it = lst.begin(); std::advance(it, 2); // 将迭代器移动到位置 2 lst.insert(it, 3); // lst 现在包含 {1, 2, 3, 4, 5} // 在位置 0 前插入 2 个 0 lst.insert(lst.begin(), 2, 0); // lst 现在包含 {0, 0, 1, 2, 3, 4, 5} // 在末尾插入另一个 list 的元素 std::list<int> lst2 = {6, 7, 8}; lst.insert(lst.end(), lst2.begin(), lst2.end()); // lst 现在包含 {0, 0, 1, 2, 3, 4, 5, 6, 7, 8} -
emplace 成员函数(C++11):
- 功能:在指定位置直接构造一个元素
- 参数:
pos- 插入位置的迭代器- 构造元素所需的参数
- 返回值:指向新构造元素的迭代器
- 优点:避免了额外的拷贝或移动操作
cppstd::list<std::pair<int, std::string>> lst; auto it = lst.begin(); lst.emplace(it, 1, "one"); // 直接在指定位置构造 pair 对象
三、list 常用迭代器
list 容器提供了多种迭代器类型,用于遍历容器中的元素。需要注意的是,list 的迭代器是双向迭代器,不支持随机访问(如 it + 5 这样的操作)。
|-------------|-----------------------------|
| 迭代器 | 含义 |
| l.begin() | 第一个元素的迭代器 |
| l.end() | 最后一个元素的下一个位置迭代器(尾后迭代器或尾迭代器) |
| l.cbegin() | 第一个元素的常量迭代器(不修改元素内容) |
| l.cend() | 尾后常量迭代器(不修改元素内容) |
| l.rbegin() | 从后往前的第一个迭代器 |
| l.rend() | 从后往前的最后一个迭代器 |
| l.crbegin() | 从后往前的第一个常量迭代器 |
| l.crend() | 从后往前的最后一个常量迭代器 |
使用示例:
cpp
std::list<int> lst = {1, 2, 3, 4, 5};
// 使用正向迭代器遍历
for (auto it = lst.begin(); it != lst.end(); ++it) {
std::cout << *it << " "; // 输出: 1 2 3 4 5
}
std::cout << std::endl;
// 使用反向迭代器遍历
for (auto it = lst.rbegin(); it != lst.rend(); ++it) {
std::cout << *it << " "; // 输出: 5 4 3 2 1
}
std::cout << std::endl;
// 使用常量迭代器遍历(不能修改元素)
for (auto it = lst.cbegin(); it != lst.cend(); ++it) {
std::cout << *it << " "; // 输出: 1 2 3 4 5
// *it = 10; // 错误:常量迭代器不能修改元素
}
std::cout << std::endl;
// 移动迭代器
auto it = lst.begin();
std::advance(it, 2); // 将迭代器移动 2 个位置
std::cout << "Element at position 2: " << *it << std::endl; // 输出: 3
四、list 常用运算符
list 类重载了多种运算符,方便容器操作:
-
赋值运算符:
=:将一个 list 赋值给另一个 list
cppstd::list<int> lst1 = {1, 2, 3}; std::list<int> lst2; lst2 = lst1; // lst2 现在包含 {1, 2, 3} -
比较运算符:
==:判断两个 list 是否相等!=:判断两个 list 是否不相等<:判断一个 list 是否小于另一个 list(字典序)<=:判断一个 list 是否小于或等于另一个 list>:判断一个 list 是否大于另一个 list>=:判断一个 list 是否大于或等于另一个 list
cppstd::list<int> lst1 = {1, 2, 3}; std::list<int> lst2 = {1, 2, 4}; bool b1 = (lst1 == lst2); // false bool b2 = (lst1 < lst2); // true(第三个元素 3 < 4)
五、list 常用成员函数
|--------------------|-----------------------------|
| list l的成员函数 | 含义 |
| l.empty() | 判断是否为空 |
| l.size() | 返回 l 的数据个数 ,重要函数 |
| l.front() | 返回第一个元素的引用 ,重要函数 |
| l.push_front() | 头插 ,重要函数 |
| l.pop_front() | 头删 ,重要函数 |
| l.back() | 返回最后一个元素的引用 ,重要函数 |
| l.push_back() | 尾插 ,重要函数 |
| l.pop_back() | 尾删 ,重要函数 |
| l.insert() | 插入一个或多个元素,这个效率为常数 ,重要函数 |
| l.erase() | 删除一个或多个元素 ,重要函数 |
| l.swap() | 交换两个list的值 ,重要函数 |
| l.clear() | 清空数据 |
1.empty 成员函数
- 功能:判断 list 是否为空
- 参数:无
- 返回值 :如果 list 为空返回
true,否则返回false
cpp
std::list<int> lst1;
std::list<int> lst2 = {1, 2, 3};
std::cout << lst1.empty(); // 输出: 1 (true)
std::cout << lst2.empty(); // 输出: 0 (false)
2.size 成员函数
- 功能:返回 list 中元素的个数
- 参数:无
- 返回值 :元素个数,类型为
size_t
cpp
std::list<int> lst = {1, 2, 3, 4, 5};
std::cout << lst.size(); // 输出: 5
3.front 成员函数
- 功能:返回 list 中第一个元素的引用
- 参数:无
- 返回值:第一个元素的引用
- 说明:如果 list 为空,行为未定义
cpp
std::list<int> lst = {1, 2, 3};
std::cout << lst.front(); // 输出: 1
lst.front() = 10; // lst 现在包含 {10, 2, 3}
4.push_front 成员函数
- 功能:在 list 前端添加一个元素
- 参数:要添加的元素值
- 返回值:无
cpp
std::list<int> lst = {2, 3, 4};
lst.push_front(1); // lst 现在包含 {1, 2, 3, 4}
5.pop_front 成员函数
- 功能:删除 list 前端的一个元素
- 参数:无
- 返回值:无
- 说明:如果 list 为空,行为未定义
cpp
std::list<int> lst = {1, 2, 3, 4};
lst.pop_front(); // lst 现在包含 {2, 3, 4}
lst.pop_front(); // lst 现在包含 {3, 4}
6.back 成员函数
- 功能:返回 list 中最后一个元素的引用
- 参数:无
- 返回值:最后一个元素的引用
- 说明:如果 list 为空,行为未定义
cpp
std::list<int> lst = {1, 2, 3};
std::cout << lst.back(); // 输出: 3
lst.back() = 30; // lst 现在包含 {1, 2, 30}
7.push_back 成员函数
- 功能:在 list 后端添加一个元素
- 参数:要添加的元素值
- 返回值:无
cpp
std::list<int> lst = {1, 2, 3};
lst.push_back(4); // lst 现在包含 {1, 2, 3, 4}
lst.push_back(5); // lst 现在包含 {1, 2, 3, 4, 5}
8.pop_back 成员函数
- 功能:删除 list 后端的一个元素
- 参数:无
- 返回值:无
- 说明:如果 list 为空,行为未定义
cpp
std::list<int> lst = {1, 2, 3, 4, 5};
lst.pop_back(); // lst 现在包含 {1, 2, 3, 4}
lst.pop_back(); // lst 现在包含 {1, 2, 3}
9.insert 成员函数
- 功能:在指定位置插入元素
- 参数:
- 版本 1:
pos, value- 在迭代器 pos 前插入 value - 版本 2:
pos, count, value- 在迭代器 pos 前插入 count 个 value - 版本 3:
pos, first, last- 在迭代器 pos 前插入迭代器范围 [first, last) 中的元素
- 版本 1:
- 返回值:指向新插入的第一个元素的迭代器
cpp
std::list<int> lst = {1, 2, 4, 5};
// 在位置 2 前插入元素 3
auto it = lst.begin();
std::advance(it, 2); // 将迭代器移动到位置 2
lst.insert(it, 3); // lst 现在包含 {1, 2, 3, 4, 5}
10.erase 成员函数
- 功能:删除 list 中的元素
- 参数:
- 版本 1:
pos- 删除迭代器 pos 指向的元素 - 版本 2:
first, last- 删除迭代器范围 [first, last) 中的元素
- 版本 1:
- 返回值:指向被删除元素之后位置的迭代器
cpp
std::list<int> lst = {1, 2, 3, 4, 5};
// 删除位置 2 的元素
auto it = lst.begin();
std::advance(it, 2); // 将迭代器移动到位置 2
it = lst.erase(it); // lst 现在包含 {1, 2, 4, 5},it 指向 4
// 删除从位置 1 到位置 2 的元素
auto start = lst.begin();
std::advance(start, 1); // 移动到位置 1
auto end = start;
std::advance(end, 2); // 移动到位置 3
lst.erase(start, end); // lst 现在包含 {1, 5}
11.swap 成员函数
- 功能:交换两个 list 的内容
- 参数:另一个 list 对象
- 返回值:无
cpp
std::list<int> lst1 = {1, 2, 3};
std::list<int> lst2 = {4, 5, 6};
lst1.swap(lst2); // lst1 现在包含 {4, 5, 6},lst2 现在包含 {1, 2, 3}
12.clear 成员函数
- 功能:删除 list 中的所有元素
- 参数:无
- 返回值:无
cpp
std::list<int> lst = {1, 2, 3, 4, 5};
lst.clear();
std::cout << lst.size(); // 输出: 0
std::cout << lst.empty(); // 输出: 1 (true)
六、list 特有成员函数
|------------------|--------------|
| list l特有成员函数 | 含义 |
| l.merge() | 链表合并 |
| l.remove(val) | 删除所有和val相同元素 |
| l.remove_if() | 删除符合条件的元素 |
| l.reverse() | 反转链表中的元素 |
| l.sort() | 排序(默认为升序) |
| l.splice() | 链表连结 |
| l.unique() | 删除重复元素 |
1.merge 特有成员函数
- 功能:合并两个已排序的 list
- 参数:
other- 另一个已排序的 list
- 返回值:无
- 说明:合并后,other 变为空
cpp
std::list<int> lst1 = {1, 3, 5};
std::list<int> lst2 = {2, 4, 6};
lst1.merge(lst2); // lst1 现在包含 {1, 2, 3, 4, 5, 6},lst2 为空
2.remove 特有成员函数
- 功能:删除所有值等于指定值的元素
- 参数:要删除的值
- 返回值:无
cpp
std::list<int> lst = {1, 2, 3, 2, 4, 2, 5};
lst.remove(2); // lst 现在包含 {1, 3, 4, 5}
3.remove_if 特有成员函数
- 功能:删除所有满足指定条件的元素
- 参数:一个返回 bool 的函数对象或 lambda 表达式
- 返回值:无
cpp
std::list<int> lst = {1, 2, 3, 4, 5, 6};
// 删除所有偶数
lst.remove_if([](int n) { return n % 2 == 0; }); // lst 现在包含 {1, 3, 5}
4.reverse 特有成员函数
- 功能 :反转 list 中元素的顺序
- 参数:无
- 返回值:无
cpp
std::list<int> lst = {1, 2, 3, 4, 5};
lst.reverse(); // lst 现在包含 {5, 4, 3, 2, 1}
5.sort 特有成员函数
- 功能 :对 list 中的元素进行排序
- 参数:可选的比较函数
- 返回值:无
cpp
std::list<int> lst = {5, 2, 8, 1, 9};
lst.sort(); // lst 现在包含 {1, 2, 5, 8, 9}
// 使用自定义比较函数(降序)
lst.sort(std::greater<int>()); // lst 现在包含 {9, 8, 5, 2, 1}
6.splice 特有成员函数
- 功能:将一个 list 中的元素转移到另一个 list 中
- 参数:
- 版本 1:
pos, other- 将 other 中的所有元素转移到 pos 前 - 版本 2:
pos, other, it- 将 other 中 it 指向的元素转移到 pos 前 - 版本 3:
pos, other, first, last- 将 other 中 [first, last) 范围内的元素转移到 pos 前
- 版本 1:
- 返回值:无
- 说明:转移后,原 list 中的元素被移除
cpp
std::list<int> lst1 = {1, 2, 3};
std::list<int> lst2 = {4, 5, 6};
// 将 lst2 中的所有元素转移到 lst1 的末尾
lst1.splice(lst1.end(), lst2);
// lst1 现在包含 {1, 2, 3, 4, 5, 6},lst2 为空
// 重新初始化 lst2
lst2 = {7, 8, 9};
// 将 lst2 中的第一个元素转移到 lst1 的开头
auto it = lst2.begin();
lst1.splice(lst1.begin(), lst2, it);
// lst1 现在包含 {7, 1, 2, 3, 4, 5, 6},lst2 现在包含 {8, 9}
7.unique 特有成员函数
- 功能:删除连续的重复元素,只保留一个
- 参数:可选的比较函数
- 返回值:无
cpp
std::list<int> lst = {1, 1, 2, 2, 2, 3, 4, 4, 5};
lst.unique(); // lst 现在包含 {1, 2, 3, 4, 5}
七、综合练习
练习 1:list 基本操作
cpp
#include <iostream>
#include <list>
int main() {
// 创建并初始化 list
std::list<int> lst = {3, 4, 5};
// 在前端添加元素
lst.push_front(2);
lst.push_front(1);
// 在后端添加元素
lst.push_back(6);
lst.push_back(7);
// 输出当前 list
std::cout << "Current list: ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
// 访问元素
std::cout << "Front: " << lst.front() << std::endl;
std::cout << "Back: " << lst.back() << std::endl;
// 删除前端和后端元素
lst.pop_front();
lst.pop_back();
// 输出修改后的 list
std::cout << "After pop_front and pop_back: ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
// 在中间插入元素
auto it = lst.begin();
std::advance(it, 2);
lst.insert(it, 10);
// 输出插入后的 list
std::cout << "After insert: ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
// 删除中间元素
it = lst.begin();
std::advance(it, 1);
lst.erase(it);
// 输出删除后的 list
std::cout << "After erase: ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
// 检查 list 状态
std::cout << "Size: " << lst.size() << std::endl;
std::cout << "Empty: " << (lst.empty() ? "Yes" : "No") << std::endl;
return 0;
}
练习 2:使用 list 特有成员函数
cpp
#include <iostream>
#include <list>
int main() {
// 创建并初始化 list
std::list<int> lst = {5, 2, 8, 1, 9, 3, 7, 4, 6};
// 排序
lst.sort();
std::cout << "After sort: ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
// 反转
lst.reverse();
std::cout << "After reverse: ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
// 创建另一个 list 并合并
std::list<int> lst2 = {10, 11, 12};
lst.merge(lst2);
std::cout << "After merge: ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
std::cout << "lst2 size: " << lst2.size() << std::endl; // 应该为 0
// 添加重复元素并去重
lst.push_back(5);
lst.push_back(5);
lst.push_back(7);
std::cout << "Before unique: ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
lst.unique();
std::cout << "After unique: ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
// 删除特定元素
lst.remove(5);
std::cout << "After remove 5: ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
// 删除满足条件的元素
lst.remove_if([](int n) { return n > 8; });
std::cout << "After remove_if (>8): ";
for (int x : lst) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
练习 3:使用 list 实现一个简单的链表
cpp
#include <iostream>
#include <list>
#include <string>
class Student {
public:
std::string name;
int age;
double score;
Student(std::string n, int a, double s) : name(n), age(a), score(s) {}
void display() const {
std::cout << "Name: " << name << ", Age: " << age << ", Score: " << score << std::endl;
}
};
// 自定义比较函数,按分数降序排序
bool compareByScore(const Student& s1, const Student& s2) {
return s1.score > s2.score;
}
int main() {
// 创建存储 Student 对象的 list
std::list<Student> students;
// 添加学生
students.emplace_back("Alice", 18, 95.5);
students.emplace_back("Bob", 19, 88.0);
students.emplace_back("Charlie", 17, 92.5);
students.emplace_back("David", 18, 85.0);
// 显示所有学生
std::cout << "All students: " << std::endl;
for (const auto& student : students) {
student.display();
}
// 按分数排序
students.sort(compareByScore);
std::cout << "\nStudents sorted by score: " << std::endl;
for (const auto& student : students) {
student.display();
}
// 删除年龄小于 18 的学生
students.remove_if([](const Student& s) { return s.age < 18; });
std::cout << "\nStudents after removing under 18: " << std::endl;
for (const auto& student : students) {
student.display();
}
// 反转顺序
students.reverse();
std::cout << "\nStudents in reverse order: " << std::endl;
for (const auto& student : students) {
student.display();
}
return 0;
}