C++ STL容器 —— forward_list 用法详解

C++ STL容器 —— forward_list 用法详解

写在前面:近期正在学习C++的STL容器,因此在这里做一下日志记录,主要介绍一些容器基本成员函数的用法, 配上实际用例,并不涉及原理。但别人的博客终究是别人的, 最好自己上手操作一下.
写的不好, 请大神手下留情.

下面说的 “运行之后” 表示: 运行上个语句之后的结果.
一行如果说的太长的话, 就得拖动下面的进度条才能看到后面的内容, 非常麻烦
因此将一段话分成了多行,就像现在这种形式

简介

头文件: # include < forward_list >
动态单向链表, 将 list 容器的末端封住, 不能直接的访问和操作
个人感觉, 只对成员函数来说, forward_list更像一个链表
点击前往: list 成员函数用法详解

构造函数

forward_list <int> fl, fl1;
//定义 int 类型的链表

forward_list <char> flch;
//定义 char 类型的链表

forward_list <string> flstr;
//定义 string 类型的链表

forward_list <int> fl2(10);
//定义拥有 10 个元素的链表, 每个元素都为 0

forward_list <int> fl3(5, 30);
//定义拥有 5 个元素的链表,并全部初始化为 30

forward_list <int> fl4 = { 1,2,3,4 };
//定义拥有 4 个空间的链表, 初始化为{1,2,3,4}

forward_list <int> fl5{ 1,2,3,4 };
//同上

forward_list <int> fl6(fl);
//定义新容器, 拷贝 fl 所有的元素

forward_list <int> fl7(fl.begin(), fl.end());
//定义新容器, 拷贝 l 区间内所有的元素

访问 / 赋值

迭代器

分为:begin、end、cbegin、cend、before_begin、cbefore_begin
使用方法:

auto it=fl.begin(); //相当于指针,用 *it 访问

fl.begin(); 返回指向fl第一个元素的迭代器
fl.end(); 返回指向fl最后一个元素下一个元素的迭代器
fl.cbegin(); 返回指向fl第一个元素的迭代器, 类型为const
fl.before_begin(); 返回指向第一个元素之前的迭代器

例: 使用正向遍历 fl 数组

forward_list <int> fl{ 1,2,3,4,5,6 };
for (auto it = fl.begin(); it != fl.end(); it++) {
	//注意这里是不等于end, 而不是小于end
	cout << *it <<' ';
}
输出结果为: 
1 2 3 4 5 6

begin和cbegin的区别
可以通过fl.begin()修改 fl 的值
不能通过fl.cbegin()修改 fl 的值

下标 / at

不支持下标 [] 和 at 函数随机访问容器内元素,只能通过迭代器访问

assign (赋值函数)
fl.assign(2, 3);
//将 2 个 3 赋值给 fl
//例:fl={5,6,7}
//运行之后 fl={3,3}

fl.assign(fl1.begin(), fl1.end());
//将区间内的元素赋值给 fl
//例:fl={5,6,7}, fl1={1,2,3,4}
//运行之后 fl={1,2,3,4}
swap (交换函数)
fl.swap(fl1);
//交换两个容器的内容
//例:fl={1,2,3,4}, fl1={5,6,7}
//运行之后, fl={5,6,7}, fl1={1,2,3,4}

常用函数

fl.push_front(4);
//在头部插入元素 4 
//例:fl={1,2,3}
//运行之后, fl={4,1,2,3}

fl.pop_front();
//删除第一元素
//例:fl={1,2,3,4}
//运行之后, fl={2,3,4}

fl.front();
//返回第一元素
//例:fl={1,2,3,4}
//fl.front()就等于 1
	
fl.clear();
//清空容器

fl.empty();
//容器为空返回 true, 否则返回 false

长度 / 空间 / 容量相关函数

fl.max_size();
//返返回 fl 元素个数的最大值

fl.resize(3);
//设置 fl 的 size
//例:fl={1,2,3,4,5,6}
//运行之后 fl={1,2,3}, 如果尺寸变小,多余的部分截掉
//例:fl={1,2}
//运行之后 fl={1,2,0}, 如果尺寸变大,新空间用 0 代替
我也不太清楚为什么forward_list 容器没有 size 这个成员函数
既然 size 都没有, 为什么会有 resize, 反正就是很迷

fl.resize(3, 2);
//设置 fl 的 size,如果尺寸变大,新空间全部用 2 代替
//例: fl={1,3}
//运行之后 fl={1,3,2}

添加元素

insert_after (插入函数)
fl.insert_after(fl.begin(), 3);
//在位置之后插入元素 3
//例: fl={1,2}
//运行之后 fl={1,3,2}

fl.insert_after(fl.begin(), 2, 3);
//在位置之后插入 2 个元素 3
//例: fl={1,2}
//运行之后 fl={1,3,3,2}

fl.insert_after(fl.begin(), fl1.begin(), fl1.end());
//在 fl 位置之后插入 fl1 区间的元素
//例: fl={1,2}, fl1={5,6,7},
//运行之后 fl={1,5,6,7,2}
emplace (插入函数)
fl.emplace_front();
//在容器的头部插入一个元素, 默认为 0
//例: fl={1,2}
//运行之后 fl={0,1,2}

fl.emplace_front(5);
//在容器的头部插入一个元素 5
//例: fl={1,2}
//运行之后 fl={5,1,2}

fl.emplace_after(fl.begin(), 5);
//在位置之后插入元素 5
//例: fl={1,2}
//运行之后 fl={1,5,2}

emplace系列 / push_front 和 insert的区别

  1. 原理上
    emplace 是直接在容器的位置上创建变量, 不需要生成对象
    push_front / insert 是先生成对象, 然后将对象的内容复制到容器里面
  2. 功能上
    emplace / push_front 只能插入一个元素
    insert 可以插入多个元素
  3. 性能上
    emplace 的速度要更快一点
merge (合并函数)
fl.merge(fl1); 
//将 fl1 的全部元素转移到 fl 
//保证转移之前的 fl/fl1 有序, 转移后的 fl 同样有序, 默认升序
//例: fl={1,3,5}, fl1={2,4,6}
//执行之后, fl={1,2,3,4,5,6}, fl1={};

fl.merge(fl1, greater <int>());
//将 fl1 的全部元素转移到 fl, 排序准则为降序
//例: fl={5,3,1}, fl1={6,4,2}
//执行之后, fl={6,5,4,3,2,1}, fl1={};

fl.merge(fl1, op); 
// 将 fl1 的全部元素转移到 fl, 排序准则为 op
splice_after (拼接函数)
fl.splice_after(fl.begin(), fl1);
// 将 fl1 转移到 fl 的位置之后
//例: fl={1,2}, fl1={5,6,7},
//运行之后 fl={1,5,6,7,2}, fl1={};

fl.splice_after(fl.begin(), fl1, fl1.begin());
//将 fl1 所指元素转移到 fl 的位置之后
//例: fl={1,3,5}, fl1={2,4,6}
//执行之后, fl={1,2,3,5}, fl1={4,6};

fl.splice_after(fl.begin(), fl1, fl1.begin(),fl1.end());
//将 fl1 区间内元素转移到 fl 的位置之后
//例: fl={1,2}, fl1={5,6,7},
//运行之后 fl={1,5,6,7,2}, fl1={};

insert / merge / splice 三个插入函数的区别
a.函数名(b)
将容器 b 的内容插入到容器 a 中

insert 函数就是正常的将容器 b 的内容复制插入到容器 a 中
merge 函数在使用之前两个容器必须具有相同的顺序(升序/降序/自定义的顺序), 是将容器 b 的内容按照一定的顺序移动插入到容器 a 中, 会将容器 b 中插入的内容删除
splice 函数是将容器 b 的内容移动插入到容器 a 中, 会将容器 b 中插入的内容删除

删除元素

erase_after (删除函数)

返回一个迭代器,该迭代器指向被删除元素后面的元素(这个是重点)

fl.erase_after(fl.begin());
//删除指向位置之后的元素
//例: fl={1,2,3}
//运行之后 fl={1,3}, 返回指向元素 3 的迭代器

fl.erase_after(fl.begin(), fl.end());
//删除区间内的元素(保留区间内的第一个元素)
//例: fl={1,2,3}
//运行之后 fl={1}
remove系列 (移除函数)
fl.remove(3);
// 删除所有值为 3 的元素
//例: fl={1,2,3,3,4,3,3}
//运行之后 fl={1,2,4}

fl.remove_if([](int a) { return a > 3; });
//删除大于 3 的元素
//例: fl={1,2,3,3,4,4,5}
//运行之后 fl={1,2,3,3}

fl.remove_if(op);
// 删除使 op 为true的元素
bool op(int a) {
// 10~100 返回 false, 其余返回 true
//其实就是删除10~100之外的数
	return a < 10 || a>100;
}
//例: fl={1,2,10,50,60,100,111}
//运行之后 fl={10,50,60,100}

unique (排重函数)
fl.unique();
//删除相邻的相同元素, 只留一个
//例: fl={1,2,3,3,3,4,3,3,6}
//运行之后 fl={1,2,3,4,3,6}

erase / remove / unique 三个删除函数的区别
erase 函数是通过迭代器查找到元素之后, 进行删除
remove 函数是通过 特定条件 查到元素之后, 进行删除
unique 函数只将相邻的相同元素删除, 但是并没有真正达到排重的效果

更改数据

reverse (翻转函数)
fl.reverse();
//翻转容器
//例:fl={1,2,3,4}
//运行之后, fl={4,3,2,1}
sort (排序函数)
fl.sort();//升序排序
//例: fl={1,2,3,5,4,1,3}
//运行之后 fl={1,1,2,3,3,4,5}

fl.sort(greater<int>());//降序排序
//例: l={1,2,3,5,4,1,3}
//运行之后 l={5,4,3,3,2,1,1}

fl.sort(op); //以 op 为准则, 将所有元素排序

sort 和 unique 函数结合
正常来说是不会用到 unique 函数的, 他一般和 sort 成员函数配套使用, 达到将容器中相同的多余元素删除的效果(真正意义上的排重)
例如:

fl={2,5,1,6,1,3,2,4,1,5,6};
直接执行 unique 函数是不能真正做到排重的
只有先进行 sort 排序, 再执行 unique 函数, 才能达到要求
fl.sort();
fl.unique();
执行之后, fl={1,2,3,4,5,6}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值