103 std::forward_list (单向链表)


作者Lou Xiao, deepseek创建时间2025-04-02 17:40:46更新时间2025-04-02 17:40:46

1. 基本概念

1.1 定义与特性

  • 单向链表:每个元素只指向下一个元素,没有指向前一个元素的指针
  • 头节点:包含指向第一个元素的指针
  • STL容器:C++标准模板库中的序列容器
  • 内存效率:比std::list更节省内存(每个节点少一个指针)

1.2 时间复杂度

操作时间复杂度
插入/删除已知位置O(1)
随机访问O(n)
查找O(n)

2. 基本操作

2.1 包含头文件

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 #include <forward_list>

2.2 声明与初始化

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 std::forward_list<int> fl1; // 空链表
2 std::forward_list<int> fl2(5, 10); // 5个元素,每个都是10
3 std::forward_list<int> fl3 = {1, 2, 3}; // 初始化列表
4 std::forward_list<int> fl4(fl3); // 拷贝构造
5 std::forward_list<int> fl5(fl4.begin(), fl4.end()); // 范围构造

2.3 元素访问

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 front(); // 访问第一个元素
2 // 没有back(), at(), operator[]等方法

3. 迭代器

3.1 迭代器类型

  • iterator:可读写
  • const_iterator:只读

3.2 获取迭代器

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 before_begin(); // 返回第一个元素之前的迭代器
2 begin(); // 返回第一个元素的迭代器
3 end(); // 返回尾后迭代器
4 cbefore_begin(); // const版本
5 cbegin(); // const版本
6 cend(); // const版本

4. 容量操作

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 empty(); // 判断是否为空
2 max_size(); // 返回可能的最大元素数量
3 // 没有size()方法,因为计算size()是O(n)操作

5. 修改操作

5.1 插入操作

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 push_front(const T& value); // 头部插入
2 emplace_front(Args&&... args); // 头部构造插入
3
4 insert_after(pos, value); // 在pos之后插入
5 insert_after(pos, count, value);// 插入count个value
6 insert_after(pos, first, last); // 插入范围
7 insert_after(pos, {list}); // 插入初始化列表
8
9 emplace_after(pos, args...); // 在pos之后构造插入

5.2 删除操作

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 pop_front(); // 删除头部元素
2
3 erase_after(pos); // 删除pos之后的元素
4 erase_after(first, last); // 删除范围
5
6 clear(); // 清空链表

5.3 其他修改

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 resize(count); // 调整大小
2 resize(count, value); // 调整大小并用value填充
3
4 swap(other); // 交换两个链表内容
5
6 merge(other); // 合并两个有序链表
7 merge(other, comp); // 带比较函数的合并
8
9 sort(); // 排序
10 sort(comp); // 带比较函数的排序
11
12 reverse(); // 反转链表
13
14 unique(); // 删除连续重复元素
15 unique(pred); // 带谓词的unique
16
17 remove(value); // 删除所有等于value的元素
18 remove_if(pred); // 删除满足谓词的元素

6. 特殊操作

6.1 拼接操作

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 splice_after(pos, other); // 移动other所有元素
2 splice_after(pos, other, it); // 移动other中it之后的元素
3 splice_after(pos, other, first, last); // 移动other中范围

6.2 比较操作

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 operator==, !=, <, <=, >, >= // 按字典序比较

7. 使用示例

1.双击鼠标左键复制此行;2.单击复制所有代码。
                                
                                    
1 #include <iostream>
2 #include <forward_list>
3 #include <algorithm>
4
5 int main() {
6 // 创建并初始化
7 std::forward_list<int> fl = {1, 2, 3, 4, 5};
8
9 // 在头部插入
10 fl.push_front(0);
11
12 // 遍历
13 for (auto it = fl.begin(); it != fl.end(); ++it) {
14 std::cout << *it << " ";
15 }
16 std::cout << "\n";
17
18 // 删除第二个元素
19 auto it = fl.begin();
20 fl.erase_after(it);
21
22 // 使用算法
23 fl.remove_if([](int n){ return n > 3; });
24
25 // 排序
26 fl.sort(std::greater<int>());
27
28 // 范围for遍历
29 for (int n : fl) {
30 std::cout << n << " ";
31 }
32
33 return 0;
34 }

8. 注意事项

  1. 没有size():因为计算size()需要遍历整个链表,是O(n)操作
  2. 插入删除位置:所有插入删除操作都是基于"after"的
  3. 迭代器失效
    • 插入操作不会使任何迭代器失效
    • 删除操作只会使被删除元素的迭代器失效
  4. 内存局部性:不如vector/array,因为元素分散在内存各处
  5. 适用场景
    • 需要频繁在头部插入/删除
    • 内存受限环境
    • 不需要随机访问
    • 需要中间频繁插入/删除

9. 性能比较

操作forward_listlistvectordeque
头部插入O(1)O(1)O(n)O(1)
尾部插入O(n)O(1)O(1)O(1)
中间插入O(1)O(1)O(n)O(n)
随机访问O(n)O(n)O(1)O(1)
内存开销最小较大最小中等

std::forward_list 常用 API 的整理表格

名称用途原型代码示例注释
push_front在链表头部插入元素void push_front(const T& value);
void push_front(T&& value);
cpp<br>std::forward_list<int> list;<br>list.push_front(42);<br>插入后,新元素成为第一个元素。
emplace_front在头部直接构造元素(避免拷贝)template<class... Args> void emplace_front(Args&&... args);cpp<br>list.emplace_front(42); // 直接构造<br>更高效,适合复杂对象。
pop_front删除头部元素void pop_front();cpp<br>list.pop_front();<br>若链表为空,行为未定义。
insert_after在指定位置后插入元素iterator insert_after(const_iterator pos, const T& value);cpp<br>auto it = list.insert_after(list.before_begin(), 10);<br>返回指向新元素的迭代器。pos 必须有效。
emplace_after在指定位置后直接构造元素template<class... Args> iterator emplace_after(const_iterator pos, Args&&... args);cpp<br>list.emplace_after(it, 20);<br>类似 insert_after,但避免临时对象拷贝。
erase_after删除指定位置后的元素iterator erase_after(const_iterator pos);cpp<br>it = list.erase_after(list.before_begin());<br>返回被删除元素的下一个元素的迭代器。
clear清空链表void clear() noexcept;cpp<br>list.clear();<br>删除所有元素,保持 forward_list 为空。
splice_after将另一个链表的元素移动到当前链表void splice_after(const_iterator pos, forward_list& other);cpp<br>list1.splice_after(list1.before_begin(), list2);<br>other 的所有元素移动到 pos 之后,other 变为空。
remove删除所有等于指定值的元素void remove(const T& value);cpp<br>list.remove(42);<br>遍历链表,删除所有匹配项。
remove_if删除满足条件的元素template<class Predicate> void remove_if(Predicate pred);cpp<br>list.remove_if([](int x) { return x % 2 == 0; });<br>对每个元素调用 pred,删除返回 true 的元素。
unique删除连续重复元素void unique();cpp<br>list.unique();<br>仅保留连续相同元素的第一个。
sort对链表排序(默认升序)void sort();
template<class Compare> void sort(Compare comp);
cpp<br>list.sort();<br>list.sort(std::greater<int>());<br>稳定排序,时间复杂度为 O(n log n)。
merge合并两个已排序链表void merge(forward_list& other);cpp<br>list1.merge(list2); // list1 和 list2 必须已排序<br>合并后 other 为空,结果链表保持有序。
reverse反转链表顺序void reverse() noexcept;cpp<br>list.reverse();<br>操作后,原第一个元素变为最后一个。
before_begin获取头节点前驱的迭代器iterator before_begin() noexcept;cpp<br>auto it = list.before_begin();<br>用于在链表头部插入元素(配合 insert_after)。
empty检查链表是否为空bool empty() const noexcept;cpp<br>if (list.empty()) { /* ... */ }<br>返回 true 表示链表为空。
max_size返回链表可容纳的最大元素数量size_type max_size() const noexcept;cpp<br>size_t max = list.max_size();<br>由系统或库实现限制。

关键特性说明:

  1. 单向性forward_list 仅支持单向遍历,无 size() 方法(需手动计算)。
  2. 迭代器失效:插入/删除操作通常只影响被操作节点及其相邻节点的迭代器。
  3. 性能:所有操作均为 O(1) 或 O(n),适合频繁插入/删除场景。
文章目录