一、list是什么
→list官方文档←
在数组中,数据在逻辑空间和物理空间上都是连续的。

而链表中的数据在逻辑上时连续的在物理空间上不是连续的。所以可以更好的利用空间,但是不能随机访问。
访问时只能访问下一个,就是单向链表 ,可以访问上一个和下一个,就是双向链表

STL的list就是:C 语言里的双向链表,被 C++ 封装好了,你不用自己写结构体、不用自己管理指针,直接拿来用就行。
二、list的特点
1. 任意位置插入 / 删除元素效率极高(O (1))
vector在插入或删除元素时,需要移动后面所有元素,效率是 O(n);
list 是双向链表,只需要修改节点的指针指向,不移动任何元素,无论在头部、中间、尾部操作,时间复杂度都是固定的 O(1)。
2. 高效的链表拼接(splice)
list 提供 splice() 函数,可以把另一个 list 的节点直接拼接到当前 list
时间复杂度 O(1),不拷贝、不移动任何元素,仅修改指针;
vector 做类似操作必须拷贝数据,效率较慢。
3. 内存分配灵活,无空间浪费
vector 是连续内存,会预分配多余空间,存在内存浪费;
list 每个元素独立分配节点内存,用多少分配多少,没有冗余空间;
不会因为扩容导致大量内存拷贝。
4.不支持随机访问
不能用 [] 或 .at() 直接访问第 k 个元素,只能从头 / 尾遍历,查找慢(O (n));
5.内存占用大
每个节点都要存储前后指针,内存占用比 vector 高;
6.遍历速度略慢
节点不连续,遍历速度慢于 vector。
三、list的使用
3.1 list的初始化

| 名称 | 使用示例 | 功能说明 |
|---|---|---|
| default(默认构造) | list<int> lst1; | 创建一个空链表,无任何元素 |
| fill(填充构造) | list<int> lst2(5, 10); | 5 个元素,每个都是 10 |
| range(迭代器初始化) | list<int> lst4(src.begin() + 1, src.end() - 1) | 用 [first, last) 区间元素构造 |
| copy(拷贝构造) | list<int> lst5(lst2); | 复制 lst2 |
这里和之前学习的容器很统一,因为他们都是顺序容器。
使用示例
在使用时要使用"#include<list>"头文件
cpp
#include <iostream>
#include <list>
using namespace std;
void print(const list<int>& lst) {
for (int x : lst) cout << x << " ";
cout << endl;
}
int main() {
// 1. 默认构造:空链表
list<int> lst1;
cout << "1. 默认构造: ";
print(lst1);
// 2. 填充构造:5个10
list<int> lst2(5, 10);
cout << "2. 填充构造: ";
print(lst2);
// 3. 迭代器区间构造
list<int> src = {1,2,3,4,5};
list<int> lst3(src.begin(), src.end());
cout << "3. 迭代器构造: ";
print(lst3);
// 4. 拷贝构造
list<int> lst4(lst2);
cout << "4. 拷贝构造: ";
print(lst4);
return 0;
}
3.2 list类对象的容量操作

| 名称 | 使用示例 | 功能说明 |
| size | lst.size() | 获取list中实际存储的元素个数 |
| empty | lst.empty() | 检测list是否为空,为空返回true,否则返回false |
|---|
使用示例
cpp
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> v1;
cout << "是否为空:" << boolalpha << v1.empty() << endl;
cout << "元素个数:" << v1.size() << endl;
v1.push_back(1);
v1.push_back(2);
cout << "是否为空:" << boolalpha << v1.empty() << endl;
cout << "元素个数:" << v1.size() << endl;
return 0;
}
3.3 list类对象的访问及遍历操作


| 名称 | 使用示例 | 功能说明 |
|---|---|---|
| begin() end() | s.begin() s.end () | begin() 获取指向第一个元素的迭代器;end() 获取指向最后一个元素下一个位置的迭代器 |
| rbegin() rend() | s.rbegin () s.rend () | rbegin() 获取指向最后一个元素的反向迭代器;rend() 获取指向第一个元素前一个位置的反向迭代器 |
| 范围 for(C++11) | for (char ch : s) {cout << ch;} | 更简洁的遍历方式,底层等价于迭代器遍历 |
| front() | lst.front() | 返回 list 第一个元素的引用 |
| back() | lst.back() | 返回 list 最后一个元素的引用 |
这里少了[]访问。
使用示例
cpp
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> lst = {10, 20, 30};
// 1. begin() + end() 正向遍历
cout << "正向遍历:";
for (auto it = lst.begin(); it != lst.end(); ++it)
cout << *it << " ";
cout << endl;
// 2. rbegin() + rend() 反向遍历
cout << "反向遍历:";
for (auto it = lst.rbegin(); it != lst.rend(); ++it)
cout << *it << " ";
cout << endl;
// 3. 范围for(最简单)
cout << "范围for:";
for (int x : lst)
cout << x << " ";
cout << endl;
// 4. front() 第一个元素
cout << "第一个元素:" << lst.front() << endl;
// 5. back() 最后一个元素
cout << "最后一个元素:" << lst.back() << endl;
return 0;
}
3.4 list类对象的修改操作

| 名称 | 使用示例 | 功能说明 |
| push_front(val) | | 在 list 首元素前插入值为 val 的元素 |
| pop_front() | | 删除 list 中第一个元素 |
| push_back(val) | | 在 list 尾部插入值为 val 的元素 |
| pop_back() | | 删除 list 中最后一个元素 |
| insert(pos, val) | | 在迭代器 pos 指向的位置前插入值为 val 的元素 |
| erase(pos) | | 删除迭代器 pos 指向的元素 |
| swap(other) | | 交换两个 list 的内容 |
| clear() | 清空 list 中的所有有效元素 |
|---|
使用示例
cpp
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> l;
// 1. 头尾添加
l.push_back(10); // 容器:[10]
l.push_front(20); // 容器:[20, 10]
l.push_back(30); // 容器:[20, 10, 30]
// 2. insert 插入
auto it = l.begin();
l.insert(++it, 50); // 在20后面插入50 → [20, 50, 10, 30]
// 3. 删除头尾
l.pop_front(); // 删除第一个20 → [50, 10, 30]
l.pop_back(); // 删除最后30 → [50, 10]
// 4. erase 删除指定位置
l.erase(l.begin()); // 删除第一个50 → [10]
// 5. clear 清空
l.clear(); // 清空 → 元素个数:0
// 6. swap 交换两个list
list<int> l1 = {1,2};
list<int> l2 = {3,4};
l1.swap(l2); // l1变成[3,4],l2变成[1,2]
return 0;
}