C++ STL容器—— forward_list 成员函数用法详解
写在前面:近期正在重新学习C++的STL容器,因此准备将STL函数的用法详细记录一下,主要介绍一些基本成员函数的用法, 外加实际的例子,并不涉及原理。其实了解这些函数最好的方法还是需要自己上手操作一下.
写的不好, 请大神手下留情.
下面说的 “运行之后” 表示: 运行上个语句之后的结果.
一行如果说的太长的话, 就得拖动下面的进度条才能看到后面的内容, 非常麻烦
因此将一段话分成了多行,就像现在这种形式
目录
- C++ STL容器—— forward_list 成员函数用法详解
- 简介
- 构造函数
- 迭代器
- 常用函数
- assign(赋值函数)
- 容量与长度函数
- insert_after(插入函数)
- emplace系列(插入函数)
- merge(合并函数)
- splice_after(拼接函数)
- erase_after(删除函数)
- remove系列(移除函数)
- unique(排重函数)
- sort(排序函数)
简介
需要头文件:# include < forward_list>
动态单向链表, 其实就是将 list 容器的尾部封住, 让你不能直接的访问和操作, 点击前往: list 成员函数用法详解
与 list 容器的区别
list 容器两端都可以访问和操作, 给我的感觉更像是一个不能随机访问的 vector 容器
forward_list 只能在头部进行操作, 其实也可以通过 insert 成员函数在尾部插入, 他的一些函数更有链表的感觉.
构造函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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 的所有元素复制给 fl6 forward_list <int> fl7(fl.begin(), fl.end()); //将范围内的元素复制给 l7 //不能使用下标 [] 随机访问 |
迭代器
包括: begin、end、cbegin、cend、before_begin、cbefore_begin
注意区别.
使用方法:
1 | auto it=fl.begin(); //相当于指针,用 *it 访问 |
fl.begin(); 返回指向fl第一个元素的迭代器
fl.end(); 返回指向fl最后一个元素下一个元素的迭代器
fl.cbegin(); 返回指向fl第一个元素的迭代器, 类型为const
fl.before_begin(); 返回指向第一个元素之前的迭代器
例: 使用正向遍历 fl 数组
1 2 3 4 5 6 7 | 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 |
遍历
fl.begin(),fl.begin()+1,···,fl.end()-1,fl.end()
begin和cbegin的区别
可以通过fl.begin()修改 fl 的值 (具体可不可以需要看 fl )
不能通过fl.cbegin()修改 fl 的值
常用函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | fl.push_front(4); //在头部插入元素 4, vector 没有这个函数 //例:fl={1,2,3} //运行之后, fl={4,1,2,3} fl.pop_front(); //删除第一个元素, vector 没有这个函数 //例:fl={1,2,3,4} //运行之后, fl={2,3,4} fl.front(); //返回 fl 的第一个元素 //例:fl={1,2,3,4} //fl.front()就等于 1 fl.clear(); //清空 fl 容器 fl.empty(); //返回 fl 容器是否为空, 空的返回 true, 非空返回 false fl.swap(fl1); //将 fl 与 fl1 交换 //例:fl={1,2,3,4}, fl1={5,6,7} //运行之后, fl={5,6,7}, fl1={1,2,3,4} fl.reverse(); //将容器的所有元素进行翻转 //例:fl={1,2,3,4} //运行之后, fl={4,3,2,1} |
assign(赋值函数)
1 2 3 4 5 6 7 8 9 | 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} |
容量与长度函数
这一部分, 有点绕.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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(插入函数)
返回指向插入位置的迭代器(即: 第一个参数的下一个位置)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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()); //在指向位置的后面插入 fl1 范围内的元素 //例: fl={1,2}, fl1={5,6,7}, //运行之后 fl={1,5,6,7,2} |
emplace系列(插入函数)
emplace_front 返回空, emplace_after返回执行插入位置的迭代器
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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的区别
- 原理上
emplace 是直接将插入的内容放进容器里面, 不需要生成对象
push_front / insert 是先生成对象, 然后将对象的内容复制到容器里面 - 功能上
emplace / push_front 只能插入一个元素
insert 可以插入多个元素 - 性能上
emplace的速度要更快一点
merge(合并函数)
合并两个已经排序的链表, 合并之前两个链表必须有序, 而且顺序相同, 按照同样的顺序进行合并, 合并之后清空第二个容器(fl1).
1 2 3 4 5 6 7 8 9 10 11 12 | fl.merge(fl1); //将 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, cmp); //将 fl1 的内容按照自定义依据合并到到 fl 里 |
splice_after(拼接函数)
将第二个容器 (fl1) 的元素插入到第一个容器 (fl) 迭代器指向的下一个位置, 同时删除 fl1 中插入到 fl 的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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(删除函数)
返回一个迭代器,该迭代器指向被删除元素后面的元素(这个是重点)
1 2 3 4 5 6 7 8 9 10 | 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系列(移除函数)
通过特定条件查找到之后删除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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(cmp);//将符合 cmp 条件的元素删除 bool cmp(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(排重函数)
1 2 3 4 | 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 函数只将相邻的相同元素删除, 没有达到真正排重的效果
sort(排序函数)
因为 list 不能随机访问, sort 函数不能使用, 因此提出一个 sort成员函数, 作用和效果我认为是差不多的.
1 2 3 4 5 6 7 8 9 10 11 12 | fl.sort(); //升序排序 //例: fl={1,2,3,5,4,1,3} //运行之后 fl={1,1,2,3,3,4,5} l.sort(greater<int>()); //降序排序 //例: l={1,2,3,5,4,1,3} //运行之后 l={5,4,3,3,2,1,1} l.sort(cmp); //自定义排序依据 cmp |
sort 和 unique 函数结合
正常来说是不会用到 unique 函数的, 他一般和 sort 成员函数配套使用, 达到将容器中相同的多余元素删除的效果(真正意义上的排重)
例如:
1 2 3 4 5 6 | 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} |