目录
[1.定义 forward_list 对象](#1.定义 forward_list 对象)
[二、向 forward_list 对象中添加元素](#二、向 forward_list 对象中添加元素)
[三、forward_list 常用迭代器](#三、forward_list 常用迭代器)
[四、forward_list 常用运算符](#四、forward_list 常用运算符)
[五、forward_list 常用成员函数](#五、forward_list 常用成员函数)
[1.empty 成员函数](#1.empty 成员函数)
[2.front 成员函数](#2.front 成员函数)
[3.push_front 成员函数](#3.push_front 成员函数)
[4.pop_front 成员函数](#4.pop_front 成员函数)
[5.insert_after 成员函数](#5.insert_after 成员函数)
[6.erase_after 成员函数](#6.erase_after 成员函数)
[六、forward_list 特有成员函数](#六、forward_list 特有成员函数)
[1.merge 特有成员函数](#1.merge 特有成员函数)
[2.remove 特有成员函数](#2.remove 特有成员函数)
[3.remove_if 特有成员函数](#3.remove_if 特有成员函数)
[4.reverse 特有成员函数](#4.reverse 特有成员函数)
[5.sort 特有成员函数](#5.sort 特有成员函数)
[6.unique 特有成员函数](#6.unique 特有成员函数)
[练习 1:forward_list 基本操作](#练习 1:forward_list 基本操作)
[练习 2:使用 forward_list 特有成员函数](#练习 2:使用 forward_list 特有成员函数)
[练习 3:使用 forward_list 实现一个简单的队列](#练习 3:使用 forward_list 实现一个简单的队列)
前言
forward_list 是 C++11 引入的标准库容器,定义在 <forward_list> 头文件中,位于 std 命名空间内。它是一种单向链表(单链表) ,只支持从前往后遍历,不支持随机访问,但在链表头部的插入和删除操作非常高效。
一、定义及初始化
使用forward list,必须包含头文件<forward_list>:
cpp
#include <forward_list>
1.定义 forward_list 对象
cpp
#include <forward_list>
// 定义一个存储 int 类型的 forward_list
std::forward_list<int> flist;
// 定义一个存储 std::string 类型的 forward_list
std::forward_list<std::string> strFlist;
2.初始化方式
-
默认初始化:创建一个空 forward_list
cppstd::forward_list<int> flist; // 空 forward_list -
列表初始化:
cppstd::forward_list<int> flist = {1, 2, 3, 4, 5}; std::forward_list<int> flist2{1, 2, 3, 4, 5}; // 与上面等价 -
使用另一个 forward_list 初始化:
cppstd::forward_list<int> flist1 = {1, 2, 3, 4, 5}; std::forward_list<int> flist2 = flist1; // 拷贝初始化 std::forward_list<int> flist3(flist1); // 拷贝构造 -
使用迭代器范围初始化:
cppstd::forward_list<int> flist1 = {1, 2, 3, 4, 5}; std::forward_list<int> flist2(flist1.begin(), flist1.end()); // 包含 flist1 的所有元素 // 从其他容器初始化 std::vector<int> vec = {6, 7, 8, 9, 10}; std::forward_list<int> flist3(vec.begin(), vec.end()); // 包含 vec 的所有元素 -
使用填充构造函数:
cpp// 注意:forward_list 没有接受元素个数和初始值的构造函数 // 可以使用生成器或循环来填充 std::forward_list<int> flist; for (int i = 0; i < 5; ++i) { flist.push_front(10); } // 此时 flist 包含 {10, 10, 10, 10, 10},但顺序是反的 // 可以使用 reverse() 来反转 flist.reverse(); // 现在 flist 包含 {10, 10, 10, 10, 10}
二、向 forward_list 对象中添加元素
forward_list 是单向链表,因此只能在头部或指定位置之后添加元素。
1.在头部添加元素
-
push_front 成员函数:
- 功能:在 forward_list 头部添加一个元素
- 参数:要添加的元素值
- 返回值:无
cppstd::forward_list<int> flist = {2, 3, 4}; flist.push_front(1); // flist 现在包含 {1, 2, 3, 4} -
emplace_front 成员函数(C++11):
- 功能:在 forward_list 头部直接构造一个元素
- 参数:构造元素所需的参数
- 返回值:无
- 优点:避免了额外的拷贝或移动操作,比 push_front 更高效
cppstd::forward_list<std::pair<int, std::string>> flist; flist.emplace_front(1, "one"); // 直接在头部构造 pair 对象 flist.push_front({2, "two"}); // 先构造临时 pair 对象,再移动到头部
2.在指定位置之后添加元素
-
insert_after 成员函数:
- 功能:在指定迭代器位置之后插入元素
- 参数:
- 版本 1:
pos, value- 在迭代器 pos 之后插入 value - 版本 2:
pos, count, value- 在迭代器 pos 之后插入 count 个 value - 版本 3:
pos, first, last- 在迭代器 pos 之后插入迭代器范围 [first, last) 中的元素
- 版本 1:
- 返回值:指向新插入的第一个元素的迭代器
cppstd::forward_list<int> flist = {1, 3, 4, 5}; // 在第一个元素之后插入元素 2 auto it = flist.begin(); // 指向第一个元素 1 flist.insert_after(it, 2); // flist 现在包含 {1, 2, 3, 4, 5} // 在头部之后插入 2 个 0 it = flist.begin(); // 指向第一个元素 1 flist.insert_after(it, 2, 0); // flist 现在包含 {1, 0, 0, 2, 3, 4, 5} // 在指定位置之后插入另一个 forward_list 的元素 std::forward_list<int> flist2 = {6, 7, 8}; it = flist.end(); // 注意:forward_list 的 end() 返回的是尾后迭代器,不能用于 insert_after // 应该找到最后一个元素 it = flist.begin(); while (std::next(it) != flist.end()) { ++it; } flist.insert_after(it, flist2.begin(), flist2.end()); // flist 现在包含 {1, 0, 0, 2, 3, 4, 5, 6, 7, 8} -
emplace_after 成员函数(C++11):
- 功能:在指定迭代器位置之后直接构造一个元素
- 参数:
pos- 插入位置之前的迭代器- 构造元素所需的参数
- 返回值:指向新构造元素的迭代器
- 优点:避免了额外的拷贝或移动操作
cppstd::forward_list<std::pair<int, std::string>> flist; auto it = flist.before_begin(); // 使用 before_begin() 获取首前迭代器 flist.emplace_after(it, 1, "one"); // 在头部之后构造 pair 对象
三、forward_list 常用迭代器
forward_list 容器提供了多种迭代器类型,用于遍历容器中的元素。需要注意的是,forward_list 的迭代器是前向迭代器,只支持 ++ 操作,不支持 -- 操作。
-
前向迭代器:
begin():返回指向第一个元素的迭代器end():返回指向最后一个元素之后位置的迭代器before_begin():返回指向第一个元素之前位置的迭代器(首前迭代器)cbefore_begin():返回指向第一个元素之前位置的常量首前迭代器
-
常量迭代器:
cbegin():返回指向第一个元素的常量前向迭代器cend():返回指向最后一个元素之后位置的常量前向迭代器
使用示例:
cpp
std::forward_list<int> flist = {1, 2, 3, 4, 5};
// 使用前向迭代器遍历
for (auto it = flist.begin(); it != flist.end(); ++it) {
std::cout << *it << " "; // 输出: 1 2 3 4 5
}
std::cout << std::endl;
// 使用常量迭代器遍历(不能修改元素)
for (auto it = flist.cbegin(); it != flist.cend(); ++it) {
std::cout << *it << " "; // 输出: 1 2 3 4 5
// *it = 10; // 错误:常量迭代器不能修改元素
}
std::cout << std::endl;
// 使用首前迭代器
auto before_first = flist.before_begin();
// 在首前迭代器之后插入元素,相当于在头部插入
flist.insert_after(before_first, 0); // flist 现在包含 {0, 1, 2, 3, 4, 5}
四、forward_list 常用运算符
forward_list 类重载了多种运算符,方便容器操作:
-
赋值运算符:
=:将一个 forward_list 赋值给另一个 forward_list
cppstd::forward_list<int> flist1 = {1, 2, 3}; std::forward_list<int> flist2; flist2 = flist1; // flist2 现在包含 {1, 2, 3} -
比较运算符:
==:判断两个 forward_list 是否相等!=:判断两个 forward_list 是否不相等<:判断一个 forward_list 是否小于另一个 forward_list(字典序)<=:判断一个 forward_list 是否小于或等于另一个 forward_list>:判断一个 forward_list 是否大于另一个 forward_list>=:判断一个 forward_list 是否大于或等于另一个 forward_list
cppstd::forward_list<int> flist1 = {1, 2, 3}; std::forward_list<int> flist2 = {1, 2, 4}; bool b1 = (flist1 == flist2); // false bool b2 = (flist1 < flist2); // true(第三个元素 3 < 4)
五、forward_list 常用成员函数
|-------------------------|-------------------|
| forward list l的成员函数 | 含义 |
| l.empty() | 判断是否为空 |
| l.front() | 返回第一个元素的引用 |
| l.push_front() | 头插 |
| l.pop_front() | 头删 |
| l.insert_after() | 插入一个或多个元素,这个效率为常数 |
| l.erase_after() | 删除一个或多个元素 |
| l.swap() | 交换两个list的值 |
| l.clear() | 清空数据 |
1.empty 成员函数
- 功能:判断 forward_list 是否为空
- 参数:无
- 返回值 :如果 forward_list 为空返回
true,否则返回false
cpp
std::forward_list<int> flist1;
std::forward_list<int> flist2 = {1, 2, 3};
std::cout << flist1.empty(); // 输出: 1 (true)
std::cout << flist2.empty(); // 输出: 0 (false)
2.front 成员函数
-
功能:返回 forward_list 中第一个元素的引用
-
参数:无
-
返回值:第一个元素的引用
-
说明:如果 forward_list 为空,行为未定义
std::forward_list<int> flist = {1, 2, 3};
std::cout << flist.front(); // 输出: 1
flist.front() = 10; // flist 现在包含 {10, 2, 3}
3.push_front 成员函数
-
功能:在 forward_list 头部添加一个元素
-
参数:要添加的元素值
-
返回值:无
std::forward_list<int> flist = {2, 3, 4};
flist.push_front(1); // flist 现在包含 {1, 2, 3, 4}
4.pop_front 成员函数
-
功能:删除 forward_list 头部的一个元素
-
参数:无
-
返回值:无
-
说明:如果 forward_list 为空,行为未定义
std::forward_list<int> flist = {1, 2, 3, 4};
flist.pop_front(); // flist 现在包含 {2, 3, 4}
flist.pop_front(); // flist 现在包含 {3, 4}
5.insert_after 成员函数
-
功能:在指定迭代器位置之后插入元素
-
参数:
- 版本 1:
pos, value- 在迭代器 pos 之后插入 value - 版本 2:
pos, count, value- 在迭代器 pos 之后插入 count 个 value - 版本 3:
pos, first, last- 在迭代器 pos 之后插入迭代器范围 [first, last) 中的元素
- 版本 1:
-
返回值:指向新插入的第一个元素的迭代器
std::forward_list<int> flist = {1, 3, 4, 5};
// 在第一个元素之后插入元素 2
auto it = flist.begin(); // 指向第一个元素 1
flist.insert_after(it, 2); // flist 现在包含 {1, 2, 3, 4, 5}
6.erase_after 成员函数
-
功能:删除指定迭代器位置之后的元素
-
参数:
- 版本 1:
pos- 删除迭代器 pos 之后的元素 - 版本 2:
first, last- 删除从 first 之后到 last 之前的元素
- 版本 1:
-
返回值:指向被删除元素之后位置的迭代器
std::forward_list<int> flist = {1, 2, 3, 4, 5};
// 删除第一个元素之后的元素(即第二个元素)
auto it = flist.begin(); // 指向第一个元素 1
flist.erase_after(it); // flist 现在包含 {1, 3, 4, 5}// 删除从第一个元素之后到第四个元素之前的元素
it = flist.begin(); // 指向第一个元素 1
auto end_it = flist.begin();
std::advance(end_it, 3); // 移动到第四个元素 5 之前的位置
flist.erase_after(it, end_it); // flist 现在包含 {1, 5}
六、forward_list 特有成员函数
|-------------------------|--------------|
| orward list l特有成员函数 | 含义 |
| l.merge() | 链表合并 |
| l.remove(val) | 删除所有和val相同元素 |
| l.remove_if() | 删除符合条件的元素 |
| l.reverse() | 反转链表中的元素 |
| l.sort() | 排序(默认为升序) |
| l.splice_after() | 链表连结 |
| l.unique() | 删除重复元素 |
1.merge 特有成员函数
- 功能:合并两个已排序的 forward_list
- 参数:
other- 另一个已排序的 forward_list
- 返回值:无
- 说明:合并后,other 变为空
cpp
std::forward_list<int> flist1 = {1, 3, 5};
std::forward_list<int> flist2 = {2, 4, 6};
flist1.merge(flist2); // flist1 现在包含 {1, 2, 3, 4, 5, 6},flist2 为空
2.remove 特有成员函数
- 功能:删除所有值等于指定值的元素
- 参数:要删除的值
- 返回值:无
cpp
std::forward_list<int> flist = {1, 2, 3, 2, 4, 2, 5};
flist.remove(2); // flist 现在包含 {1, 3, 4, 5}
3.remove_if 特有成员函数
- 功能:删除所有满足指定条件的元素
- 参数:一个返回 bool 的函数对象或 lambda 表达式
- 返回值:无
cpp
std::forward_list<int> flist = {1, 2, 3, 4, 5, 6};
// 删除所有偶数
flist.remove_if([](int n) { return n % 2 == 0; }); // flist 现在包含 {1, 3, 5}
4.reverse 特有成员函数
- 功能:反转 forward_list 中元素的顺序
- 参数:无
- 返回值:无
cpp
std::forward_list<int> flist = {1, 2, 3, 4, 5};
flist.reverse(); // flist 现在包含 {5, 4, 3, 2, 1}
5.sort 特有成员函数
- 功能:对 forward_list 中的元素进行排序
- 参数:可选的比较函数
- 返回值:无
cpp
std::forward_list<int> flist = {5, 2, 8, 1, 9};
flist.sort(); // flist 现在包含 {1, 2, 5, 8, 9}
// 使用自定义比较函数(降序)
flist.sort(std::greater<int>()); // flist 现在包含 {9, 8, 5, 2, 1}
6.unique 特有成员函数
- 功能:删除连续的重复元素,只保留一个
- 参数:可选的比较函数
- 返回值:无
cpp
std::forward_list<int> flist = {1, 1, 2, 2, 2, 3, 4, 4, 5};
flist.unique(); // flist 现在包含 {1, 2, 3, 4, 5}
七、综合练习
练习 1:forward_list 基本操作
cpp
#include <iostream>
#include <forward_list>
int main() {
// 创建并初始化 forward_list
std::forward_list<int> flist = {3, 4, 5};
// 在头部添加元素
flist.push_front(2);
flist.push_front(1);
// 输出当前 forward_list
std::cout << "Current forward_list: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
// 访问元素
std::cout << "Front: " << flist.front() << std::endl;
// 删除头部元素
flist.pop_front();
// 输出修改后的 forward_list
std::cout << "After pop_front: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
// 在指定位置之后插入元素
auto it = flist.begin(); // 指向第一个元素 2
flist.insert_after(it, 10);
// 输出插入后的 forward_list
std::cout << "After insert_after: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
// 删除指定位置之后的元素
it = flist.begin(); // 指向第一个元素 2
flist.erase_after(it);
// 输出删除后的 forward_list
std::cout << "After erase_after: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
// 检查 forward_list 状态
std::cout << "Empty: " << (flist.empty() ? "Yes" : "No") << std::endl;
return 0;
}
练习 2:使用 forward_list 特有成员函数
cpp
#include <iostream>
#include <forward_list>
int main() {
// 创建并初始化 forward_list
std::forward_list<int> flist = {5, 2, 8, 1, 9, 3, 7, 4, 6};
// 排序
flist.sort();
std::cout << "After sort: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
// 反转
flist.reverse();
std::cout << "After reverse: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
// 创建另一个 forward_list 并合并
std::forward_list<int> flist2 = {10, 11, 12};
flist2.sort(); // 合并前需要排序
flist.sort(); // 合并前需要排序
flist.merge(flist2);
std::cout << "After merge: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
std::cout << "flist2 size: " << std::distance(flist2.begin(), flist2.end()) << std::endl; // 应该为 0
// 添加重复元素并去重
flist.push_front(5);
flist.push_front(5);
flist.push_front(7);
std::cout << "Before unique: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
flist.sort(); // 去重前最好先排序,确保重复元素连续
flist.unique();
std::cout << "After unique: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
// 删除特定元素
flist.remove(5);
std::cout << "After remove 5: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
// 删除满足条件的元素
flist.remove_if([](int n) { return n > 8; });
std::cout << "After remove_if (>8): ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
练习 3:使用 forward_list 实现一个简单的队列
cpp
#include <iostream>
#include <forward_list>
class Queue {
private:
std::forward_list<int> flist;
// 用于跟踪尾部位置
std::forward_list<int>::iterator tail;
// 更新尾部迭代器
void updateTail() {
if (flist.empty()) {
tail = flist.before_begin();
} else {
tail = flist.begin();
while (std::next(tail) != flist.end()) {
++tail;
}
}
}
public:
Queue() : tail(flist.before_begin()) {}
// 入队
void enqueue(int value) {
if (flist.empty()) {
flist.push_front(value);
} else {
// 如果 tail 无效,更新它
if (tail == flist.end() || std::next(tail) != flist.end()) {
updateTail();
}
flist.insert_after(tail, value);
++tail; // 更新 tail 到新添加的元素
}
}
// 出队
void dequeue() {
if (!flist.empty()) {
flist.pop_front();
updateTail(); // 更新 tail
}
}
// 获取队首元素
int front() {
if (!flist.empty()) {
return flist.front();
}
return -1; // 表示队列为空
}
// 检查是否为空
bool empty() {
return flist.empty();
}
// 获取队列大小
size_t size() {
return std::distance(flist.begin(), flist.end());
}
// 打印队列
void print() {
std::cout << "Queue: ";
for (int x : flist) {
std::cout << x << " ";
}
std::cout << std::endl;
}
};
int main() {
Queue q;
// 入队
q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
q.enqueue(4);
q.enqueue(5);
q.print(); // 输出: Queue: 1 2 3 4 5
// 出队
q.dequeue();
q.dequeue();
q.print(); // 输出: Queue: 3 4 5
// 获取队首元素
std::cout << "Front: " << q.front() << std::endl; // 输出: Front: 3
// 检查队列状态
std::cout << "Size: " << q.size() << std::endl; // 输出: Size: 3
std::cout << "Is empty: " << (q.empty() ? "Yes" : "No") << std::endl; // 输出: Is empty: No
return 0;
}