List

C++ 的 list 就是双向链表,和 vectormap 的用法差别挺大。下面我用“中学生能听懂 + 写题够用”的方式给你讲,重点放在怎么用、哪里容易错。

一、什么是 list?

#include <list>

list 是一个双向链表:

• 每个元素都记得“前一个”和“后一个”

• 插入、删除很快

• 不支持随机访问(不能用 a[i]

一句话记忆:

vector 像数组,list 像链条

二、基本定义

list<int> a;              // 空链表
list<int> b = {1, 2, 3};  // 初始化
list<string> names;

三、常用操作速查表(重点)

功能 代码

尾部插入 a.push_back(x)

头部插入 a.push_front(x)

尾部删除 a.pop_back()

头部删除 a.pop_front()

插入 a.insert(it, x)

删除 a.erase(it)

清空 a.clear()

判空 a.empty()

元素个数 a.size()

第一个元素 a.front()

最后一个元素 a.back()

四、遍历 list(必须会用迭代器)

✅ 普通遍历(最常用)

list<int> a = {1, 2, 3};

for (auto it = a.begin(); it != a.end(); ++it) {
    cout << *it << " ";
}

⚠️ 不能写成 it < a.end()(这是 vector 的习惯)

✅ 范围 for(最简单)

for (int x : a) {
    cout << x << " ";
}

⚠️ 只读时推荐,要删除元素不要用这个。

五、插入元素(list 的强项)

list<int> a = {1, 2, 3};
auto it = a.begin();
++it;                    // 指向 2
a.insert(it, 99);        // 在 2 前插入 99

结果:

1 99 2 3

insert 不会让其他迭代器失效(这是 list 的优点)

六、删除元素(重点,容易错)

1️⃣ 删除单个元素

auto it = a.begin();
++it;
a.erase(it);

2️⃣ 遍历删除(正确写法)

❌ 错误写法:

for (auto it = a.begin(); it != a.end(); ++it) {
    if (*it == 2)
        a.erase(it);   // ❌ it 失效
}

✅ 正确写法(C++11):

for (auto it = a.begin(); it != a.end(); ) {
    if (*it == 2)
        it = a.erase(it);  // ✅ 接收返回值
    else
        ++it;
}

3️⃣ 删除头尾

a.pop_front();
a.pop_back();

⚠️ 删除前一定要判断非空:

if (!a.empty()) a.pop_front();

七、list 没有的功能(常考)

❌ 不能用下标访问

cout << a[1];      // ❌ 编译错误
cout << a.at(1);   // ❌

✅ 只能靠迭代器移动:

auto it = a.begin();
advance(it, 2);    // it 向后移动 2 步
cout << *it;

八、list 独有的好东西(竞赛常用)

1️⃣ splice(链表拼接,O(1))

list<int> a = {1, 2, 3};
list<int> b = {4, 5};

a.splice(a.end(), b);  // 把 b 接到 a 后面

结果:

a: 1 2 3 4 5
b: 空

✅ 比拷贝快得多

2️⃣ remove(按值删除)

a.remove(2); // 删除所有值为 2 的元素

3️⃣ unique(去重,前提是已排序)

a.sort();
a.unique();

九、list vs vector(一句话区分)

对比 vector list

底层 数组 双向链表

随机访问 ✅ ❌

头插/头删 ❌ 慢 ✅ 快

中间插入 ❌ 慢 ✅ 快

迭代器失效 容易 不容易

👉 频繁插入删除 → list
👉 频繁访问 → vector

十、一个完整示例(适合课堂)

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> a = {1, 2, 3, 2};

    a.push_front(0);
    a.push_back(4);

    a.remove(2);   // 删除所有 2

    for (int x : a)
        cout << x << " ";
}

输出:

0 1 3 4

十一、给中学生的记忆口诀 ✅

list 是链条两头通,

插删快,访问慢;

不用下标用迭代,

erase 要接返回值。

posted @ 2026-07-08 10:44  飞花阁  阅读(31)  评论(0)    收藏  举报
//雪花飘落效果