std::list
是 C++ STL(标准模板库)中提供的一个 双向链表容器,适用于需要频繁在中间或头尾插入/删除元素的场景。
一、std::list 概述
cpp
#include <list>
-
定义:
cppstd::list<int> myList;
-
底层结构:双向链表
-
特点:
- 插入/删除效率高(O(1))
- 不能随机访问(没有
[]
操作符,不能用索引) - 每个节点存储数据 + 前后指针
二、常见用法示例
1. 创建与初始化
cpp
std::list<int> list1; // 空列表
std::list<int> list2 = {1, 2, 3, 4}; // 列表初始化
std::list<int> list3(5, 10); // 5 个值为 10 的元素
2. 插入与删除
cpp
std::list<int> myList = {1, 2, 3};
// 头尾插入
myList.push_front(0); // -> 0 1 2 3
myList.push_back(4); // -> 0 1 2 3 4
// 头尾删除
myList.pop_front(); // -> 1 2 3 4
myList.pop_back(); // -> 1 2 3
// 插入到指定位置(使用 iterator)
auto it = myList.begin();
std::advance(it, 1); // 移动到第2个元素
myList.insert(it, 10); // -> 1 10 2 3
// 删除指定位置
it = myList.begin();
std::advance(it, 2);
myList.erase(it); // -> 1 10 3
3. 遍历 list
cpp
for (auto it = myList.begin(); it != myList.end(); ++it)
std::cout << *it << " ";
for (const auto& val : myList)
std::cout << val << " ";
4. 其他常用操作
cpp
myList.clear(); // 清空
myList.empty(); // 是否为空
myList.size(); // 元素个数
myList.front(); // 第一个元素
myList.back(); // 最后一个元素
三、特殊操作
1. 去重(相邻元素)
cpp
std::list<int> lst = {1, 1, 2, 2, 3, 3};
lst.unique(); // -> 1 2 3
2. 排序
cpp
lst.sort(); // 升序排序
lst.sort(std::greater<int>()); // 降序排序
3. 反转
cpp
lst.reverse();
四、自定义类型示例
cpp
struct Person {
std::string name;
int age;
};
std::list<Person> people = {
{"Alice", 30}, {"Bob", 25}, {"Charlie", 35}
};
people.sort([](const Person& a, const Person& b) {
return a.age < b.age;
});
五、使用场景总结
需求 | 是否适合 std::list |
---|---|
快速在中间插入/删除 | ✅ 非常适合 |
随机访问元素 | ❌ 不适合(用 vector 更合适) |
大量头部插入 | ✅ |
需要排序和去重 | ✅ |
多线程场景 | ⚠️ 需要加锁(非线程安全) |
六、高级应用示例
下面是 std::list
的高级用法示范,涵盖:
- 自定义排序与
splice
- 使用
remove_if
删除特定条件元素 merge
合并已排序链表- 使用
unique
去重 - 自定义类型支持
std::list
示例1:高级用法综合示范
cpp
#include <iostream>
#include <list>
#include <algorithm>
#include <string>
struct Person {
std::string name;
int age;
// 支持排序的比较函数
bool operator<(const Person& other) const {
return age < other.age;
}
// 支持去重的等价比较函数
bool operator==(const Person& other) const {
return name == other.name && age == other.age;
}
};
void PrintList(const std::list<Person>& lst, const std::string& title) {
std::cout << title << ":\n";
for (const auto& p : lst) {
std::cout << " " << p.name << ", age " << p.age << "\n";
}
std::cout << std::endl;
}
int main() {
std::list<Person> group1 = { {"Alice", 30}, {"Bob", 25}, {"Charlie", 28} };
std::list<Person> group2 = { {"Diana", 26}, {"Eve", 24}, {"Bob", 25} };
PrintList(group1, "Group 1");
PrintList(group2, "Group 2");
// sort + merge(合并两个已排序 list)
group1.sort(); // 按 age 升序排序
group2.sort();
group1.merge(group2); // group2 被清空
PrintList(group1, "Merged Group");
// unique 去重(需要 operator==)
group1.unique();
PrintList(group1, "After unique (去重)");
// remove_if:删除年龄小于 28 的成员
group1.remove_if([](const Person& p) {
return p.age < 28;
});
PrintList(group1, "After remove_if (age < 28)");
// splice:将一个 list 插入另一个位置
std::list<Person> newcomers = { {"Frank", 31}, {"Grace", 29} };
auto it = std::next(group1.begin());
group1.splice(it, newcomers); // 插入 newcomers 到 group1 中间
PrintList(group1, "After splice newcomers");
return 0;
}
输出:
Group 1:
Alice, age 30
Bob, age 25
Charlie, age 28
Group 2:
Diana, age 26
Eve, age 24
Bob, age 25
Merged Group:
Eve, age 24
Bob, age 25
Bob, age 25
Diana, age 26
Charlie, age 28
Alice, age 30
After unique (去重):
Eve, age 24
Bob, age 25
Diana, age 26
Charlie, age 28
Alice, age 30
After remove_if (age < 28):
Charlie, age 28
Alice, age 30
After splice newcomers:
Charlie, age 28
Frank, age 31
Grace, age 29
Alice, age 30
小结:std::list
高级用法速查
功能 | 函数 | 说明 |
---|---|---|
排序 | list.sort() |
内部比较或自定义排序 |
合并 | list.merge() |
需先排序,合并后自动排序 |
去重 | list.unique() |
删除相邻重复元素(需支持 == ) |
条件删除 | remove_if() |
按 lambda 或谓词删除 |
插入链表 | splice() |
整段迁移插入,不拷贝、零成本 |
自定义类型支持 | 重载 < 与 == |
支持排序、去重、自定义谓词 |
示例2:实现简易任务调度系统
示例支持功能:
- 添加任务(支持优先级)
- 动态执行并删除任务
- 删除过期任务
- 支持按优先级排序执行
Task 定义:
cpp
#include <iostream>
#include <list>
#include <string>
#include <chrono>
#include <functional>
#include <algorithm>
using Clock = std::chrono::steady_clock;
struct Task {
std::string name;
int priority; // 数字越大,优先级越高
Clock::time_point expireTime;
std::function<void()> action;
bool operator<(const Task& other) const {
return priority > other.priority; // 用于 sort:高优先级在前
}
};
TaskScheduler 类:
cpp
class TaskScheduler {
private:
std::list<Task> tasks;
public:
void AddTask(const Task& task) {
tasks.push_back(task);
}
void RemoveExpiredTasks() {
auto now = Clock::now();
tasks.remove_if([&](const Task& task) {
return now > task.expireTime;
});
}
void RunTopTask() {
if (tasks.empty()) return;
// 优先级排序(高优先级排前面)
tasks.sort();
auto task = tasks.front();
tasks.pop_front();
std::cout << "[Running] " << task.name << std::endl;
task.action();
}
void RunAllTasks() {
tasks.sort();
for (const auto& task : tasks) {
std::cout << "[Running] " << task.name << std::endl;
task.action();
}
tasks.clear();
}
void PrintTasks() const {
std::cout << "Scheduled Tasks:\n";
for (const auto& task : tasks) {
std::cout << " " << task.name << " (priority: " << task.priority << ")\n";
}
}
};
使用示例
cpp
int main() {
TaskScheduler scheduler;
scheduler.AddTask({
"TaskA", 1, Clock::now() + std::chrono::seconds(10),
[] { std::cout << " -> Running TaskA\n"; }
});
scheduler.AddTask({
"TaskB", 5, Clock::now() + std::chrono::seconds(5),
[] { std::cout << " -> Running TaskB\n"; }
});
scheduler.AddTask({
"TaskC", 3, Clock::now() + std::chrono::seconds(1),
[] { std::cout << " -> Running TaskC\n"; }
});
std::cout << "All tasks:\n";
scheduler.PrintTasks();
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟延时
scheduler.RemoveExpiredTasks();
std::cout << "\nTasks after removing expired:\n";
scheduler.PrintTasks();
std::cout << "\nExecuting tasks...\n";
scheduler.RunAllTasks();
}
输出示例
All tasks:
Scheduled Tasks:
TaskA (priority: 1)
TaskB (priority: 5)
TaskC (priority: 3)
Tasks after removing expired:
Scheduled Tasks:
TaskA (priority: 1)
TaskB (priority: 5)
Executing tasks...
[Running] TaskB
-> Running TaskB
[Running] TaskA
-> Running TaskA
优势
std::list
支持 任意位置插入/删除,无需重新分配内存。- 适合构建 实时任务队列 、异步处理池 、调度表系统。
- 支持
splice()
快速合并多个任务队列,零开销。
小结
操作 | 时间复杂度 |
---|---|
插入/删除(任意位置) | O(1)(已知 iterator) |
访问第 n 个元素 | O(n) |
遍历所有元素 | O(n) |