forward_list 单向链表
什么是 forward_list?
std::forward_list
是 C++11 引入的一种单向链表容器,它提供了一个高效的单链表数据结构。与 std::list
(双向链表)相比,forward_list
只能从前向后遍历,没有反向遍历的能力,但内存占用更小,在某些场景下性能更佳。
备注
forward_list
设计的主要目标是将C风格单链表的性能特性带入C++标准库,同时提供现代C++的安全性和便利性。
forward_list 的基本特性
- 单向遍历:只能从头到尾遍历
- 无大小操作:不提供
size()
方法(获取大小需要O(n)时间) - 插入和删除高效:在已知位置插入和删除元素的时间复杂度为O(1)
- 不支持随机访问:必须遍历到特定位置才能访问元素
- 内存高效:每个节点只需存储一个"下一个"指针,比双向链表节省内存
基本用法
包含头文件
#include <forward_list>
创建和初始化
// 创建空的forward_list
std::forward_list<int> list1;
// 使用初始化列表创建
std::forward_list<int> list2 = {1, 2, 3, 4, 5};
// 创建包含n个相同元素的forward_list
std::forward_list<std::string> list3(5, "hello");
// 从另一个forward_list复制
std::forward_list<int> list4 = list2;
基本操作
以下是一些 forward_list
常用的操作:
#include <iostream>
#include <forward_list>
int main() {
std::forward_list<int> myList = {10, 20, 30, 40, 50};
// 在开头插入元素
myList.push_front(5);
// 遍历并打印列表
std::cout << "List contents: ";
for (const auto& element : myList) {
std::cout << element << " ";
}
std::cout << std::endl;
// 从开头移除元素
myList.pop_front();
// 检查是否为空
if (!myList.empty()) {
std::cout << "First element: " << myList.front() << std::endl;
}
// 清空整个列表
myList.clear();
return 0;
}
输出:
List contents: 5 10 20 30 40 50
First element: 10
特殊操作和方法
插入操作
由于 forward_list
是单向链表,插入操作需要特别注意。对于中间位置的插入,它提供了 insert_after
系列函数:
#include <iostream>
#include <forward_list>
#include <string>
int main() {
std::forward_list<std::string> languages = {"Python", "Java", "JavaScript"};
// 获取指向第一个元素的迭代器
auto it = languages.begin();
// 在"Python"之后插入"C++"
languages.insert_after(it, "C++");
// 打印结果
std::cout << "Programming languages: ";
for (const auto& lang : languages) {
std::cout << lang << " ";
}
std::cout << std::endl;
return 0;
}
输出:
Programming languages: Python C++ Java JavaScript
使用 before_begin
forward_list
提供了一个特殊的迭代器 before_begin()
,它指向第一个元素之前的位置,用于在列表开头插入元素:
std::forward_list<int> numbers = {2, 3, 4};
// 在列表开头插入1
numbers.insert_after(numbers.before_begin(), 1);
// 现在numbers包含:1, 2, 3, 4
合并和拼接操作
forward_list
提供了高效的合并和拼接操作:
#include <iostream>
#include <forward_list>
#include <algorithm>
int main() {
std::forward_list<int> list1 = {1, 3, 5, 7};
std::forward_list<int> list2 = {2, 4, 6, 8};
// 确保两个列表都是已排序的
list1.sort();
list2.sort();
// 合并两个有序列表
list1.merge(list2);
std::cout << "Merged list: ";
for (int n : list1) {
std::cout << n << " ";
}
std::cout << std::endl;
// 注意:merge操作后list2将为空
std::cout << "Is list2 empty? " << (list2.empty() ? "Yes" : "No") << std::endl;
return 0;
}
输出:
Merged list: 1 2 3 4 5 6 7 8
Is list2 empty? Yes
其他常用操作
std::forward_list<int> myList = {3, 1, 4, 1, 5, 9, 2, 6};
// 排序
myList.sort(); // {1, 1, 2, 3, 4, 5, 6, 9}
// 移除指定值
myList.remove(1); // 移除所有值为1的元素
// 按条件移除
myList.remove_if([](int n){ return n % 2 == 0; }); // 移除所有偶数
// 去重(要求已排序)
myList.unique(); // 移除连续的重复元素
// 反转
myList.reverse(); // 反转列表中的元素顺序
forward_list 与 list 的比较
特性 | forward_list | list |
---|---|---|
链接方向 | 单向 | 双向 |
内存消耗 | 更小 | 较大 |
size()操作 | 不支持 | O(1)复杂度 |
反向迭代器 | 不支持 | 支持 |
push_back() | 不支持 | 支持 |
在已知位置插入 | O(1) | O(1) |