大多数算法定义在头文件algorithm中,在头文件numeric中定义了数值泛型算法。

以find算法为例:在容器的两个迭代器指定的范围内遍历,查找特定值。

int val=; auto result=find(ivec.begin(),ivec.end(),val); cout<<result<<endl;

迭代器令算法不依赖于容器,但算法依赖于元素类型的操作

算法不执行容器的操作,只会执行迭代器的操作

只读算法

  只会读取其范围之内的元素而不会改变元素

  除了find算法之外,例如accumulate算法(定义在numeric头文件中),返回范围内元素之和+指定初值

    cin>>sum;

    accumulate(ivec.cbegin(),ivec.cend(),sum);(如果是string类型,则是将string连接起来)

  对于只读算法,最好选取cbegin和cend作为迭代器

  再举操作两个序列的算法equal为例:(如果两个序列所有对应元素相同,则返回true,否则返回false)

    equal(ivec1.cbegin(),ivec1.cend(),ivec2.cbegin());

  equal算法并不要求两个序列元素类型严格一致,只要能用==比较即可

  基于此例,对于只给出第二个序列的单一迭代器的算法,都假定两序列等长(至少不能比第一个短)

写元素算法

  需要确保容器自身大小至少不小于写入的元素数目(因为算法不能改变容器大小)

   例如:fill(ivec.begin(),ivec.end(),val);将容器每个值赋为val

     fill_n(ivec.begin(),ivec.size(),val);将容器每个值赋为val

      注意:如果对空容器使用fill_n并且指定长度,会引起错误

  back_inserter(定义在iterator头文件)

    为了向容器尾部添加元素而使用的迭代器

      vector<int> ivec; auto it =back_inserter(ivec); *it=;

    这样在容器的尾部添加了一个元素,值为23

    结合fill_n使用:(添加了10个值为val的元素到ivec)

      vector<int> ivec; fill_n(back_inserter(ivec),,val);

  拷贝算法:

        auto ret=copy(begin(arr1),end(arr1),arr2);

    这样将arr1序列的值拷贝给arr2(要求arr2至少和arr1等长),返回end(arr2)

    类似copy算法,replace也具备此类替换效果:

      replace(ilst.begin(),ilst.end(),search_value,new_value);

    这样将ilst序列中所有值为search_value的元素赋值为new_value

    如果不想将原序列改变,可以将元素替换后的序列保存在其他容器中:

      replace_copy(ilst.begin(),ilst.end(),back_inserter(ivec),search_value,new_value);

    这样借助replace_copy函数和back_inserter将新的ilst保存在ivec中,原本的ilst不变

重排元素算法

  

  1. #include<iostream>
  2. #include<iterator>
  3. #include<algorithm>
  4. #include<vector>
  5. #include<string>
  6. #include<cstdlib>
  7. using namespace std;
  8. void elimDups(vector<string> &vec){
  9. //使向量按字典序排序
  10. sort(vec.begin(),vec.end());
  11. //使用unique函数重排序列,使得序列中每个词仅出现一次
  12. //获得的序列在原序列的前部,返回不重复元素的子序列的尾后迭代器
  13. auto end_unique=unique(vec.begin(),vec.end());
  14. //使用erase函数删除重复单词
  15. vec.erase(end_unique,vec.end());
  16. }
  17. int main(){
  18. string str;
  19. vector<string> svec;
  20. while(getline(cin,str)){
  21. svec.push_back(str);
  22. }
  23. for(const auto &i:svec){
  24. cout<<i<<" ";
  25. }
  26. elimDups(svec);
  27. cout<<endl;
  28. for(const auto &j:svec){
  29. cout<<j<<" ";
  30. }
  31.  
  32. }
  33. /*output:
  34. the
  35. quick
  36. red
  37. fox
  38. jumps
  39. over
  40. the
  41. slow
  42. red
  43. turtle
  44. ^Z
  45. the quick red fox jumps over the slow red turtle
  46. fox jumps over quick red slow the turtle*/

定制操作

  例如使sort接受第三个参数,此参数即为谓词(可调用的表达式,返回值可作为条件),原本sort利用<来比较元素,那么这里使用谓词来代替<作为比较的依据

  

  1. bool isShorter(const string &s1,const string &s2){
  2. return s1.size()<s2.size();}
  3. sort(svec.begin(),svec.end(),isShorter);

  这里用长度来比较字符串,而不是以字典序作为比较依据

  如果我们希望将等长的字符串以字典序比较,不等长的字符串以长度比较:

  1. void elimDups(vector<string> &vec){
  2. //使向量按字典序排序
  3. sort(vec.begin(),vec.end());
  4. //使用unique函数重排序列,使得序列中每个词仅出现一次
  5. //获得的序列在原序列的前部,返回不重复元素的子序列的尾后迭代器
  6. auto end_unique=unique(vec.begin(),vec.end());
  7. //使用erase函数删除重复单词
  8. vec.erase(end_unique,vec.end());
  9. }
  10. int main(){
  11. elimDups(svec);
  12. stable_sort(svec.begin(),svec.end(),isShorter);
  13. }

  这里使用了提供谓词的stable_sort函数,保持了等长的元素之间的字典序

  lambda表达式:(c++11)格式:[capture list](parameter list)->return type{function body};

    这里capture list是函数中定义的局部变量的列表(通常为空)

    建立调用对象时可以省略列表 (相当于参数为空)和返回类型(除非函数体中存在返回语句,否则默认为void),如:

      auto f = [ ]{return ;};   f();

    不同于普通函数,lambda不能有默认参数

    例如:等价于上述isShorter函数的lambda:

[](const string &s1,const string &s2){  return s1.size()<s2.size();}

    [ ]内为空说明lambda不使用函数内任何局部变量

    如果capture list 不为空,则函数体可以使用capture list中的变量:

     [sz](const string&s1){ return s1.size()<sz;};

    完整的biggies函数:包含find_if函数和for_each函数

  1.  void biggies(const string &s1,const string::size_type sz){
  2. elimDups(svec);
  3. stable_sort(svec.begin(),svec.end(),[](const string &s1,const string &s2){
  4. return s1.size()<s2.size();});
  5. auto wc=find_if(svec.begin(),svec.end(),[sz](const string &s){
  6. return s.size()>=sz});
  7. auto count = svec.end()-wc;
  8. for_each(wc,svec.end(),[](const string &s){cout<<s<<' ';});
  9. }

    这里find_if函数返回指向第一个长度不小于给定参数sz的元素的迭代器

    这里for_each函数接受一个可调用对象,并输出序列中每个元素调用此对象

   lambda的捕获和返回

    每当定义一个lambda时,编译器自动生成一个未命名的类类型,

    每当向函数传递一个lambda,同时定义了一个新类型和该类型的一个对象。

    与函数调用参数类似,lambda的capture list可以是值捕获也可以是引用捕获(其效应与函数参数别无二致)

    (注意:应尽量避免引用捕获或者指针捕获,如果必须如此,必须确保在调用lambda的时期内捕获的对象的值是有效的)

    与显式捕获相对应的,也可以使用隐式捕获:

    [=]表示隐式的值捕获,[&]表示隐式的引用捕获

    [=,&]表示按照调用顺序,第一个是值捕获,第二个是引用捕获(其余组合以此类推)

     可变lambda

    如果希望能够改变被捕获的变量的值,必须在参数列表首加上关键字mutable

     auto f = [sz] () mutable{return ++sz;}; 可变lambda的参数列表可以省略

   指定lambda返回类型

    例如: transform(ivec.begin(),ivec.end(),ivec.begin(),[](int i)->int{return i<?i:-});  

    这里transform函数将原序列各个元素的值替换为其绝对值(第一个和第三个参数相同==调用和输入序列首是同一位置)

以上说明了lambda的使用方法,一般较为简单的操作适合使用lambda,如果是比较复杂而且重复的操作还是调用函数比较合适

参数绑定

  标准库bind函数:(c++11)(所在头文件functional)

    如果我们写了一个函数,并且希望用此函数来代替lambda,使用bind来解决向sz形参传递参数的问题

    调用bind的格式:auto newCallable=bind(callable,args_list);

    (其中args_list中如果含有诸如_1,_2之类的名字,则用来表示newCallable中对应位置的参数)

    具体使用例如:  

  1. bool check_size(const string &s1,string::size_type sz){
  2. return s1.size()>=sz;}
  3. auto check2=bind(check_size,_1,);

    这里_1表示check2的第一个参数(也是唯一一个)就是(check_size的第一个参数)const string&,2表示sz==2

    调用check2:  string str="HELL";  bool b2=check2(str);(等效于调用check_size(str,6))

    bind语句可以作为lambda的替代品

    上述的语句中如名字_1,_2之类在使用之前需要声明名字空间:using std::placeholders::_1;之类的语句

    (也可以直接写 using namespace std::placeholders;)

  bind参数与函数对应的关系:

    auto g=bind(f,a,b,_2,c,_1);

    调用g(_1,_2);等效于调用f(a,b,_2,c,_1);

    (如果调用g(X,Y)等效于调用f(a,b,Y,c,X))

  如果希望传递给bind一个引用参数parameter,必须使用ref(parameter)或者cref(parameter)

迭代器再探

  插入迭代器

    支持的操作:it = t;在it指定的位置插入值t

    back_inserter(value);创建一个使用push_back的迭代器

    front_inserter(value);创建一个使用push_front的迭代器

    inserter(value,pos);在pos迭代器之前一个位置插入值为value的元素

    

    

    

C++Primer 5th Chap10 Generic Algorithms(未完)的更多相关文章

  1. AutoMapper介绍(未完待续、部分没实现)

    实体间转换工具.其实也可以用Json来实现同名属性.异名属性(用JsonProperty指明)的自动转换 最新版本6.11 需要使用vs2013以上.vs2012下载新版 nuget会遇到问题.只能旧 ...

  2. java泛型基础、子类泛型不能转换成父类泛型--未完待续

    参考http://how2j.cn/k/generic/generic-generic/373.html 1.使用泛型的好处:泛型的用法是在容器后面添加<Type>Type可以是类,抽象类 ...

  3. javascript有用小功能总结(未完待续)

    1)javascript让页面标题滚动效果 代码如下: <title>您好,欢迎访问我的博客</title> <script type="text/javasc ...

  4. ASP.NET MVC 系列随笔汇总[未完待续……]

    ASP.NET MVC 系列随笔汇总[未完待续……] 为了方便大家浏览所以整理一下,有的系列篇幅中不是很全面以后会慢慢的补全的. 学前篇之: ASP.NET MVC学前篇之扩展方法.链式编程 ASP. ...

  5. 关于DOM的一些总结(未完待续......)

    DOM 实例1:购物车实例(数量,小计和总计的变化) 这里主要是如何获取页面元素的节点: document.getElementById("...") cocument.query ...

  6. 我的SQL总结---未完待续

    我的SQL总结---未完待续 版权声明:本文为博主原创文章,未经博主允许不得转载. 总结: 主要的SQL 语句: 数据操作(select, insert, delete, update) 访问控制(g ...

  7. virtualbox搭建ubuntu server nginx+mysql+tomcat web服务器1 (未完待续)

    virtualbox搭建ubuntu server nginx+mysql+tomcat web服务器1 (未完待续) 第一次接触到 linux,不知道linux的确很强大,然后用virtualbox ...

  8. MVC丶 (未完待续······)

         希望你看了此小随 可以实现自己的MVC框架     也祝所有的程序员身体健康一切安好                                                     ...

  9. 一篇文章让Oracle程序猿学会MySql【未完待续】

    一篇文章让Oracle DB学会MySql[未完待续] 随笔前言: 本篇文章是针对已经能够熟练使用Oracle数据库的DB所写的快速学会MySql,为什么敢这么说,是因为本人认为Oracle在功能性方 ...

随机推荐

  1. FLUENT不同求解器离散格式选择【转载】

    转载自:http://blog.163.com/wu_yangfeng/blog/static/16189737920104158950438/ 离散格式对求解器性能的影响 控制方程的扩散项一般采用中 ...

  2. Git的使用(5) —— 在IDEA上使用

    1. 在IDEA中配置Git 前言:IDEA中鼓捣Git是真的费劲,建议还是用TortoiseGit. 打开IDEA的Settings,左侧菜单列表中的Version Control里面找到Git. ...

  3. 修改docker默认存储路径

    默认情况下,docker镜像的默认存储路径是/var/lib/docker,这相当于直接挂载系统目录下,而一般在搭系统时,这个区都不会太大,所以如果长期使用docker开发应用,就需要把默认的路径更改 ...

  4. [转]重命名PostgreSQL数据库

    初学PostgreSQL的朋友可能会有这样的疑惑:如何重命名已经建好的数据库?因为PostgreSQL默认的客户端pgAdmin III并没有地方可以让我们去修改某个现有的数据库的名称.遇到这个情况, ...

  5. At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger fo

    一.文章前言 本文是亲测有效解决At least one JAR was scanned for TLDs yet contained no TLDs问题,绝对不是为了积分随便粘贴复制然后压根都没有用 ...

  6. Confluence 实现公司wiki【转】

    Confluence是一个企业级的Wiki软件,可用于在企业.部门.团队内部进行信息共享和协同编辑一.安装过程1 安装并配置mysql [root@vm1 ~]# /etc/my.cnf charac ...

  7. CMU Database Systems - Indexes

    这章主要描述索引,即通过什么样的数据结构可以更加快速的查询到数据 介绍Hash Tables,B+tree,SkipList 以及索引的并行访问 Hash Tables hash tables可以实现 ...

  8. pip错误 ImportError: No module named 'pip_internal'

    ubuntu16.04 - wget https://bootstrap.pypa.io/get-pip.py --no-check-certificate sudo python get-pip.p ...

  9. fork 可能导致subprocess崩溃

    https://docs.python.org/zh-cn/3/library/multiprocessing.html 在 3.8 版更改: 对于 macOS,spawn 启动方式是默认方式. 因为 ...

  10. gitlab 构建常见错误

    1.前端是http服务后端是https,原因生产https,测试是http服务环境.代理后端2. java 打包程序需要运行正式数据库没连上错误.打包和跑正式的一个库.3. jenkins不能直接no ...