下面内容都是特定容器算法,也就是c++,list和forward_list特有的算法。

第一部分:成员函数算法merge(forward_list和list专用)

1.c++ primer 5th p369页上说,lst.merge(lst2) 必须lst 和lst2都是有序的,但是我自己编写程序,lst和lst2都没有顺序也是可以的,why?

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <forward_list>
#include <stack>
#include <vector>
#include <forward_list>
#include <deque>
#include <array>
#include <list>
#include <algorithm>
#include <numeric>
using namespace std;
bool compare(const int ,const int);
int main()
{
forward_list<int> f1{1,2223,3,4,5,6};
forward_list<int> l1{7,8,9};
//f1.sort();这里根本就没有运行
//l1.sort();这里也根本没有运行
//下面merge算法添加第二个参数用于比较,但是结果却不给从小到大排列?
f1.merge(l1,compare);
//这里我才开始排序
f1.sort();
for(auto i : f1)cout << i << endl;return 0;
}
bool compare(const int a,const int b)
{
return a < b;
}

上述代码在ubuntu20.04运行结果如下:

r@r:~/coml_/c++/chapter10/10.6$ g++ 2.cc -o 123
r@r:~/coml_/c++/chapter10/10.6$ ./123
1
3
4
5
6
7
8
9
2223

疑问:这个算法对于不不同类型的容器不成立?也就是说,一个forward_list,另一个是list,就不能合并。我自己的编译器是如此的。

高手如果知道也告诉我下?难道只能合并相同类型的容器???

还有为何我程序里面加了compare,运行结果却不给排序?为了,摆设?有高手就给我解释下?拜托。小弟初学者。

第二部分:算法remove

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <forward_list>
#include <stack>
#include <vector>
#include <forward_list>
#include <deque>
#include <array>
#include <list>
#include <algorithm>
using namespace std;
bool is_odd(const int );
int main()
{
//have not function parameter
forward_list<int> fint{1,2,3,45,5,32};
fint.remove(32);
for(auto i : fint)cout << i << endl;//have function parameter
forward_list<int> fint2{1,2,3,4,5,6,7};
fint2.remove_if([](const int i){return (i % 2 == 0);});
//fint2.remove_if(is_odd);
cout << endl;
for(auto i : fint2)cout << i << endl;
return 0;
}
bool is_odd(const int i)
{
return (i % 2);
}

注意一下几个问题:

1.如果使用算法remove那么参数一定是一个元素类型的值,如果使用算法remove_if,那么参数是一个函数或者是lambda表达式,总之是一个一元谓词

2.以前非成员函数版本的remove是不会删除这个元素的,因为返回位置后,删除这个元素很容的。但是现在成员函数版本remove或者remove_if会直接删除这个元素。因为你自己删除这个元素很难。多么是人性化。

下面再加几行代码,同时复习一下bind函数(用于参数绑定的),要使用它必须先添加头文件 functional,和名字空间  using namespace std::placeholders,废话不多说,直接上代码:

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <forward_list>
#include <stack>
#include <vector>
#include <forward_list>
#include <deque>
#include <array>
#include <list>
#include <algorithm>
#include <functional>
using namespace std::placeholders;
using namespace std;
bool is_odd(const int );
bool divide(const int ,const int);
int main()
{
//have not function parameter
forward_list<int> fint{1,2,3,45,5,32};
fint.remove(32);
for(auto i : fint)cout << i << endl;//have function parameter
forward_list<int> fint2{1,2,3,4,5,6,7};
fint2.remove_if([](const int i){return (i % 2 == 0);});
//fint2.remove_if(is_odd);
cout << endl;
for(auto i : fint2)cout << i << endl;
//下面再作死一下,再编写一个bind函数调用算法remove_if
//顺便复习一下bind函数,当你编写的函数要求很苛刻的时候,bind可能越有用
//删除能被5整除且大于给定整数的数
forward_list<int> fint3{10,11,12,13,14,15,16,5,0};
//define given integer number
int key;
cout << "Enter given number:"<< endl;
cin >> key;
fint3.remove_if(bind(divide,_1,key));
for(auto i : fint3)cout << i << endl;return 0;
}
bool is_odd(const int i)
{
return (i % 2);
}
//定义这个函数纯粹是为了作死,调用bind
bool divide(const int i,const int key)
{return (i % 5== 0 && i > key);}

第三部分:reverse,下面的代码包含了很多不必要的头文件。

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <forward_list>
#include <stack>
#include <vector>
#include <forward_list>
#include <deque>
#include <array>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
forward_list<int> f1{1,2,3,4};
f1.reverse();
for(auto i : f1)cout << i << endl;
return 0;
}

总结:还好,这个函数简单,没有遇到前面那么多麻烦。

第四部分:sort,本来打算不解释了。仔细一看,sort带参数版本竟然不加if,自己必须编写程序运行一下:

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <forward_list>
#include <stack>
#include <vector>
#include <forward_list>
#include <deque>
#include <array>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
//have no parameter
forward_list<int> f1{1,2,3,4};
f1.reverse();
for(auto i : f1)cout << i << " ";
cout << endl;//have parameter
forward_list<int> f2{1,2,3,4,5,6,7,8,9,10};
//按照除以5的余数大小进行排序
f2.sort([](const int i,const int j){return (i % 5 < j % 5);});for(auto i : f2)cout << i << " ";cout << endl;return 0;
}

sort带二元谓词版本后面不加if,真尼玛牛B。

第五部分:unique,简单不介绍了。

这两个函数都是重载函数,难道尼玛的有参数和无参数后面不加个if区别下?

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <forward_list>
#include <stack>
#include <vector>
#include <forward_list>
#include <deque>
#include <array>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
forward_list<int> f{1,2,3,4,5,4,5,1,2};
//sort the number by the remainder divided by 5
f.sort([](const int i,const int j){return (i%5 < j%5);});
//if remainder devided by 5 is the same,then equal
f.unique([](int i,int j){return (i %5 == j %5);});
for(auto i : f)cout << i << endl;return 0;
}

总结:unique的二元谓词参数,函数也是不加if。牛

第三部分:list的splice算法,forward_list的splice_after算法

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <forward_list>
#include <stack>
#include <vector>
#include <forward_list>
#include <deque>
#include <array>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
/*forward_list*/
//member function 1:flst.splice_after(p,flst2),insert flst2 after p
forward_list<int> f1{1,2,3,4,5,6};
forward_list<int> f2{11,22,33};
f1.splice_after(f1.begin(),f2);
for(auto i : f1)cout << i << endl;//f2 has no elements
for(auto j : f2)cout << j << endl;//member function 2:flst.splice_after(p,lst2,p2),move elements which pointed by  p2's next interator
//把p2位置之后的元素插入到p之后
forward_list<int> f21{21,23,24,35};
forward_list<int> f22{33,34,54,54};
f21.splice_after(f21.begin(),f22,++f22.begin());
for(auto i : f21)cout << i << " ";
cout << endl;
//member function3:flst.splice_after(p,lst2,b,e):把lst2中(b,e)中的元素移动到flst中p之后,注意(b,e)是两边开区间。
//把lst2的第二个到第五个元素移动到lst中
forward_list<int> lst{1,2,3,4};
forward_list<int> lst2{11,22,33,44,55,66,77,88};
int i = 0;
forward_list<int>::iterator p1 = lst2.begin(),p2 =lst2.begin();
while(i !=5)
{
++ p2;
++ i;
}
//now p2 point to 6th element of lst2,p1 point to 1th element of lst2
//注意这里(p1,p2)是两边开区间,因为forward_list本身的特性,是把p1后面且p2前面的元素移动到lst中
lst.splice_after(lst.before_begin(),lst2,p1,p2);
cout << "lst is:" << endl;
for(auto i : lst)cout << i << " ";cout << endl;
/*list*/
list<int> l1{1,2,3,4,5};
list<int> l2{11,22,33};
list<int> l3{1024,1025,1026};
l1.splice(l1.begin(),l2);
for(auto i : l1)cout << i << " ";
cout << endl;
cout << "list"<< " " << endl;
//member function 2: insert element which pointed by l3.begin() into l1(before ++ l1.begin())
l1.splice(++l1.begin(),l3,l3.begin());
for(auto i : l1)cout << i << " ";
cout << endl;
//member function 3:lst.splice(p,lst2,b,e):把lst2中的[b,e)中的元素移动到lst中的p之前,注意[b,e)是前面闭区间,后面开区间.//把lst_new中第3-6个元素移动到lst2_new中
list<int> lst_new{20,21,22,23,24,25};
list<int> lst2_new{30,31,32,33,34,35,36,37,38};
int ii = 0,jj = 0;
list<int>::iterator it1 = lst2_new.begin();
list<int>::iterator it2 = lst2_new.begin();
while(ii != 2)
{
it1 ++;
ii ++;
}
while(jj != 6)
{
it2 ++;
++ jj;
}
lst_new.splice(lst_new.begin(),lst2_new,it1,it2);
cout << "print:" << endl;
for(auto i : lst_new)cout << i << " ";cout << endl;
return 0;
}

总结:splice和splice_after算法的异同点:

1.splice是往给定迭代器前面插入,而splice_after是往给定的迭代器位置的后面插入,例如

lst.splice(p,lst2)在p的前面插入lst2,flst.splice_after(p,flst2)

lst.splice(p,lst2,p2)在p的前面插入lst2中p2所指元素,flst.splice(p,flst2,p2),把p2后面的一个元素插入到p的后面

lst.splice(p,lst2,b,e)在p的前面插入lst2中[b,e)的元素,flst.splice(p,flst2,b,e)  把flst2中(b,e)的元素插入到p的后面

2.总结

lst.splice()插入的是【b,e)区间或者是某个迭代器p2所指的元素,往p的前面插入

lst.splice_after插入的是(b,e)区间的元素,或者是某个迭代器p2后面的一个元素,插入的范围和插入的位置均不一样,splice_after插入位置均位于某个迭代器之后,splice插入的位置是某个迭代器之前。

splice插入的元素正好是传统上的p2所指的或者前开后9闭区间。而splice_after插入的元素是某个元素后面的元素或者是两边开区间范围的元素。

相同点:都要插入和被插入的两个链表(容器)的类型相同.要么都是list,要么都是forward_list

顺便把那个课后习题也弄了把。下面就是自己编写的答案:

10.6节习题自己编写的答案

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <forward_list>
#include <stack>
#include <vector>
#include <forward_list>
#include <deque>
#include <array>
#include <list>
#include <algorithm>
using namespace std;void print(const list<string> &);int main(int argc,char *argv[])
{
//be careful:out must be specified to fstream::out or ofstream::out or
//fstream::app,etc..
//注意,这里fstream 流的 out必须指明文件模式是 out模式或者app模式才能自动创建文件。否则打开文件会失败。
fstream in,out(argv[2],ofstream::out);
in.open(argv[1]);
if(!out)cout << "open file failure" << endl;list<string> lstr;
string str;
while(in >> str)
{
lstr.push_back(str);
}
lstr.sort();
lstr.sort([](const string &s1,const  string &s2){return (s1.size() < s2.size());});
lstr.unique();
print(lstr);
cout << argv[1] << endl;
cout << argv[2] << endl;for(auto i : lstr)out << i << endl;return 0;
}void print(const list<string> &s)
{for(auto i : s)cout << i << " ";}

注意一点:c++输出文件流要么指明是ofstream对象,如果是fstream对象必须指明out模式或者app模式才能自动创建文件。

也就是说,fstream文件流对象在不指名任何模式的情况下,编译器不负责创建文件。

splice算法再举个例子

//以下例子都运行过全部通过
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <forward_list>
#include <stack>
#include <vector>
#include <forward_list>
#include <deque>
#include <array>
#include <list>
#include <algorithm>
using namespace std;
int main()
{forward_list<int> l1 {1,2,3,4,5},l2{6,7,8};//insert all elements of l2 to l1//l1.splice_after(l1.begin(),l2);//insert some element of l2 to l1//l1.splice_after(l1.before_begin(),l2,++l2.begin());//insert elements from a scope   of l2 to l2,note that the scope is (),rather than [),becouse forward_listl1.splice_after(l1.before_begin(),l2,l2.begin(),l2.end());for(auto i : l1)cout << i << endl;
return 0;
}

c++ 特定容器算法(sort,merge,reverse,remove,unique)相关推荐

  1. C++ Primer 5th笔记(chap 10)泛型算法 :特定容器算法list

    list容器结合自己的结构专门实现了更为高效的算法 操作 定义 附注 lst.merga(lst2) 将来自lst2的元素合并入lst.lst和lst2都必须是有序的.元素将从lst2中删除.在合并之 ...

  2. 经典排序算法 - 归并排序Merge sort

    经典排序算法 - 归并排序Merge sort 原理,把原始数组分成若干子数组,对每一个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到全部合并完,形成有序的数组 举例 无序数组[6 ...

  3. TiDB 源码阅读系列文章(十五)Sort Merge Join

    2019独角兽企业重金招聘Python工程师标准>>> 什么是 Sort Merge Join 在开始阅读源码之前, 我们来看看什么是 Sort Merge Join (SMJ),定 ...

  4. 深入探讨JS中的数组排序函数sort()和reverse()

    最近在研究Javascript发现了其中一些比较灵异的事情.有点让人感到无语比如: alert(typeof( NaN == NaN));//结果为假. alert(typeof( NaN != Na ...

  5. C++实验课任务(多态--容器--算法)

    C++实验课任务(多态–容器–算法) 题目的基本实现 代码如下(具体细节处的分析见代码中/**/里的部分): #pragma once #include <string> #include ...

  6. 【Qt】通过QtCreator源码学习Qt(九):容器算法总结

    一.简介 本节总结QtCreator中封装的容器算法接口,源码文件的路径src/libs/utils/algorithm.h. 算法接口包括:判断.查找.删除.统计.排序.转换.拆分.过滤 二.算法源 ...

  7. 表的连接方式:NESTED LOOP、HASH JOIN、SORT MERGE JOIN

    表连接方式及使用场合 NESTED LOOP 对于被连接的数据子集较小的情况,nested loop连接是个较好的选择.nested loop就是扫描一个表,每读到一条记录,就根据索引去另一个表里面查 ...

  8. Nested Loop,Sort Merge Join,Hash Join

    三种连接工作方式比较: Nested loops 工作方式是从一张表中读取数据,访问另一张表(通常是索引)来做匹配,nested loops适用的场合是当一个关联表比较小的时候,效率会更高. Merg ...

  9. LeetCode算法入门- Merge Two Sorted Lists -day15

    LeetCode算法入门- Merge Two Sorted Lists -day15 题目描述: Merge two sorted linked lists and return it as a n ...

最新文章

  1. 苹果手表可以运行 ruby 脚本了
  2. Java基础笔记(入门,语法基础,流程控制,数组)
  3. .NET Framework VS .NET Core
  4. 带有数据库的动态级联菜单
  5. php中的date()函数d y m l等字母的表示方法
  6. 安卓最新版本_nyearlabel安卓下载-nyearlabel最新版本下载v1.2.3 安卓版
  7. 魔百和服务器网站,【当贝市场】魔百盒首页诊断显示网络异常解决办法
  8. 国外3个设计师插画等必备PNG免扣素材网站分享
  9. 教你将手机里的图片转成PDF的2种方法
  10. layui导出Excel功能的两种方式的尝试
  11. 下载Synechococcus elongatus UTEX 2973(accession no.为GCA_000817325.1 )的基因组注释文件,统计其中染色体序列(CP006471.1)前10
  12. 【使用老电脑win7下载miniconda】
  13. 【SAP】SAP SD,中英日专业名词对照表
  14. “网红”白鸦创立6年的有赞,为何不敌同样诞生于微信生态3年的拼多多?
  15. PRIMES is in P
  16. BPM软件_财务报销流程管理解决方案_K2工作流引擎
  17. 【Kubernetes】K8s集群operator模式安装minio
  18. 计算机在石油工程中应用文献综述,石油与天然气工程领域工程硕士专业学位基本要求第一部分概况.PDF...
  19. 不要轻易放过一个30几岁的程序员
  20. e光的matlab,【e光嫩肤的效果怎么样】_功效_作用-大众养生网

热门文章

  1. mac os 切换网络优先级
  2. C# IO操作(五)文件的递归加载
  3. 【Socket】linux网络多路复用IO技术
  4. JavaScript中对象成员的可见性
  5. SpringBoot整合Mybatis完整详细版
  6. Java+MyEclipse+Tomcat (三)配置MySQL及查询数据显示在JSP网页中
  7. LeetCode 数据库 182. 查找重复的电子邮箱
  8. 某公司有一台打印、复印一体机,需要将购买成本分年均摊到隔年的费用中。请编写一个程序,根据用户输入的购买金额和预计使用年限计算每年的分摊费用。要求对输入异常进行适当的处理。
  9. uwsgi+python+flask+nginx服务器部署
  10. 7.Vue 列表渲染