泛型算法本身不会执行容器的操作,它们只会运行于迭代器之上,执行迭代器的操作。因此算法可能改变容器中保存的元素,也可能在容器内移动元素,但永远不会直接添加或删除元素。

只读算法:

accumulate:

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <list>
  5. #include <forward_list>
  6. #include <deque>
  7. #include <string>
  8. using namespace std;
  9.  
  10. int main(void){
  11. vector<int> v(, );
  12. int sum = accumulate(v.cbegin(), v.cend(), );
  13. cout << sum << endl;//
  14. sum = accumulate(v.cbegin(), v.cend(), );//第三个参数是和的初始值且决定了函数中使用哪个加法运算以及返回值的类型
  15. cout << sum << endl;//
  16. cout << endl;
  17.  
  18. list<string> l = {"fjs", "afjkflf", "wwe"};
  19. string str = accumulate(l.cbegin(), l.cend(), string(""));//注意不能用c风格的字符串,c风格字符串上没有重载+
  20. cout << str << endl;//fjsafjkflfwwe
  21.  
  22. deque<double> q(, 1.1);
  23. double cnt = accumulate(q.cbegin(), q.cend(), 0.0);//第三个参数决定了使用何总类型的+
  24. double cc = accumulate(q.cbegin(), q.cend(), );
  25. cout << cnt << endl;//
  26. cout << cc << endl;//
  27.  
  28. return ;
  29. }

显然,只要支持随机访问(能用迭代器遍历)的容器都支持 accumulate 算法

注意:第三个参数是和的初始值且决定了函数中使用哪个加法运算以及返回值的类型

不能用c风格的字符串,c风格字符串上没有重载+

equal:

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <list>
  5. using namespace std;
  6.  
  7. int main(void){
  8. vector<string> v(, "hello");
  9. vector<string> v1(, "hello");
  10. list<string> l1(, "hello");
  11. list<const char*> l2 = {"hello", "hello", "hello", "hello", "zzz"};
  12. list<const char*> l3 = {"hello", "hello", "hello", "hello", "zzz"};
  13.  
  14. bool flag1 = equal(v.cbegin(), v.cend(), l1.cbegin());//可以两个不同类型的容器之间比较,只要元素之间支持==运算符即可
  15. bool flag2 = equal(v.cbegin(), v.cend(), l2.cbegin());
  16. bool flag3 = equal(l2.cbegin(), l2.cend(), l3.cbegin());
  17. // bool flag4 = equal(v.cbegin(), v.cend(), v1.cbegin());//会运行时出错,只接受一个单一的迭代器来表示第二个序列的算法,都假定第二个序列至少与第一个序列一样长
  18. cout << flag1 << endl;//
  19. cout << flag2 << endl;//
  20. cout << flag3 << endl;//
  21.  
  22. cout << endl;
  23.  
  24. return ;
  25. }

注意:可以两个不同类型的容器之间比较,只要元素之间支持 == 运算符即可

只接受一个单一的迭代器来表示第二个序列的算法,都假定第二个序列至少与第一个序列一样长

写容器元素的算法:

fill/fill_n:

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. using namespace std;
  5.  
  6. int main(void){
  7. vector<int> v, v1, v2;//定义三个空容器
  8. fill(v.begin(), v.end(), );
  9. fill_n(v1.begin(), v1.size(), );
  10.  
  11. // fill_n(v2.begin(), 10, 0);//错误,v2是一个空容器,越界了
  12. v2.reserve();//给v2分配5个int的空间
  13. fill_n(v2.begin(), , );//v2虽然分配了空间,但其仍然是一个空容器,不改变容器大小无法向其中赋值
  14. cout << v2.size() << endl;//
  15. cout << v2.capacity() << endl;//
  16. return ;
  17. }

注意:使用 fill_n 第一个元素传入一个普通迭代器时如果我们第二个参数不传 v.size() 的话很容易导致越界

fill_n 本身不改变容器的大小,若传给 fill_n 的第一个迭代器是一个普通迭代器的话无法给空容器赋值

back_inserter:

  1. #include <iostream>
  2. #include <iterator>
  3. #include <vector>
  4. using namespace std;
  5.  
  6. int main(void){
  7. vector<int> v1;//空向量
  8. auto it = back_inserter(v1);
  9. //back_inserter接受一个指向容器的引用,返回一个与该容器绑定的插入迭代器,当我们通过此迭代器赋值时,
  10. //赋值运算会调用push_back将一个具有给定值的元素添加到容器中
  11. *it = ;//此时v1中有一个元素0
  12. for(const auto indx : v1){
  13. cout << indx << endl;
  14. }
  15.  
  16. vector<int> v2(, );
  17. *back_inserter(v2) = ;
  18. for(const auto indx : v2){
  19. cout << indx << " ";
  20. }
  21. cout << endl;//1 1 1 1 0
  22.  
  23. vector<int> v3;
  24. fill_n(back_inserter(v3), , );//添加10个0到v3中
  25. for(const auto indx : v3){
  26. cout << indx << " ";
  27. }
  28. cout << endl;//0 0 0 0 0
  29. return ;
  30. }

注意:back_inserter 接受一个指向容器的引用,返回一个与该容器绑定的插入迭代器,当我们通过此迭代器赋值时,赋值运算会调用 push_back 将一个具有给定值的元素添加到容器中

fill_n 算法本质是对传入的迭代器的操作,所以给 fill_n 传入普通迭代器时不能改变对应容器的大小,若 fill_n 的第一个迭代器参数是插入迭代器时则其可以改变对应容器的大小并插入指定元素

copy:

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <list>
  4. #include <deque>
  5. #include <vector>
  6. using namespace std;
  7.  
  8. int main(void){
  9. int a1[] = {, , , , , , , , , };
  10. int a2[sizeof(a1) / sizeof(*a1)];//a2与a1的大小一样
  11. auto ret = copy(begin(a1), end(a1), begin(a2));//将a1的内容拷贝到a2,返回目标迭代器递增之后的值
  12. for(const auto indx : a2){
  13. cout << indx << " ";
  14. }
  15. cout << endl;
  16. cout << (ret == end(a2)) << endl;//
  17.  
  18. list<int> l(, );
  19. deque<int> f;
  20. copy(l.begin(), l.end(), back_inserter(f));
  21. for(const auto indx : f){
  22. cout << indx << " ";
  23. }
  24. cout << endl;//1 1 1 1 1
  25.  
  26. vector<int> v;//空容器
  27. v.reserve();//虽然该容器现在被分配了5个int空间,但其仍然是空容器
  28. copy(l.begin(), l.end(), back_inserter(v));//向空容器拷入元素,改变了元素大小,必须使用插入迭代器
  29. cout << v.size() << endl;//
  30. cout << v.capacity() << endl;//
  31. for(const auto indx : v){
  32. cout << indx << " ";
  33. }
  34. cout << endl;
  35.  
  36. vector<int> v1();//一个含有5个元素的容器
  37. copy(l.begin(), l.end(), v1.begin());//只是替换原有元素,不需要用插入迭代器
  38. for(const auto indx : v1){
  39. cout << indx << " ";
  40. }
  41. cout << endl;//1 1 1 1 1
  42. return ;
  43. }

注意:越界问题

对于要改变容器大小的地方不能用普通迭代器

replace/replace_copy

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <forward_list>
  4. #include <vector>
  5. using namespace std;
  6.  
  7. int main(void){
  8. forward_list<int> f(, );
  9. replace(f.begin(), f.end(), , );//将f中所有0替换成1024
  10. for(const auto indx : f){
  11. cout << indx << " ";
  12. }
  13. cout << endl << endl;
  14.  
  15. forward_list<int> l(, );
  16. vector<int> v;
  17. replace_copy(l.cbegin(), l.cend(), back_inserter(v), , );//将l拷贝到v并将v中元素值为0的修改成42
  18. for(const auto indx : l){
  19. cout << indx << " ";
  20. }
  21. cout << endl;
  22. for(const auto indx : v){
  23. cout << indx << " ";
  24. }
  25. cout << endl;
  26.  
  27. return ;
  28. }

注意:对于要改变容器大小的地方不能用普通迭代器,如:本例中 replace_copy 中因为 v 是个空迭代器,若以第三个参数必须用插入迭代器

重排容器元素的算法:

unique:

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. using namespace std;
  5.  
  6. void work(vector<string> &words){
  7. sort(words.begin(), words.end());//unique只剔除相邻的相同元素
  8. auto end_unique = unique(words.begin(), words.end());//将相邻的相同的元素"删除",返回一个指向不重复值范围末尾的迭代器
  9. words.erase(end_unique, words.end());//上面的"删除"并不是真的删除,只是覆盖了而已,我们通过erase真正的将其删除
  10. }
  11.  
  12. int main(void){
  13. vector<string> v = {"ac", "ab", "ac", "a", "a"};
  14. work(v);
  15. for(const auto indx : v){
  16. cout << indx << " ";
  17. }
  18. cout << endl;//a ab ac
  19.  
  20. return ;
  21. }

注意:unique 只剔除相邻的相同元素

将相邻的相同的元素 "删除",返回一个指向不重复值范围末尾的迭代器。但其不真正的删除元素,只是将重复的值移到迭代器末尾而已,也可能会将其覆盖

谓词:

谓词是一个可调用的表达式,其返回结果是一个能用作条件的值。标准库算法所使用的谓词分两类:一元谓词(意味着它们只接受单一参数) 和二元谓词(意味着它们有两个参数)。接受谓词参数的算法对输入序列中的元素调用谓词。因此,元素类型必须能转换为谓词参数类型。如:sort 能接受一个二元谓词参数,这个谓词用来代替 < 来比较元素

sort 和 stable_sort:

sort 和 stable_sort 的使用规则完全一样,有区别的是带有 stable 的是稳定排序~

partition 和 stable_partition:

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. using namespace std;
  5.  
  6. bool is_longer_than_5(const string &s){
  7. return s.size() >= ;
  8. }
  9.  
  10. int main(void){
  11. vector<string> v1 = {"fjskf", "fjslfjksl", "fjsklfk", "f", "fdds", "fjs", "fjslf"};
  12. vector<string> v2 = {"fjskf", "fjslfjksl", "fjsklfk", "f", "fdds", "fjs", "fjslf"};
  13.  
  14. auto pos1 = partition(v1.begin(), v1.end(), is_longer_than_5);//该算法是非稳定的
  15. auto pos2 = stable_partition(v2.begin(), v2.end(), is_longer_than_5);//该算法是稳定的
  16.  
  17. for(auto it = v1.begin(); it != pos1; it++){
  18. cout << *it << " ";
  19. }
  20. cout << endl;
  21.  
  22. for(auto it = v2.begin(); it != pos2; it++){
  23. cout << *it << " ";
  24. }
  25. cout << endl;
  26.  
  27. return ;
  28. }

泛型1(一些algorithm函数)的更多相关文章

  1. C#的泛型委托与闭包函数

    前些天Wendy问我说Func<T, ResultT>是个什么意思,初学C#都觉得这样的写法很奇葩,甚至觉得这样写有点诡异,其实以我来看,这是体现C#函数式编程的又一个亮点. 从MSDN上 ...

  2. Kotlin中的“忍者”函数 —— 理解泛型的能力(KAD 12)

    作者:Antonio Leiva 时间:Feb 8, 2017 原文链接:https://antonioleiva.com/generic-functions-kotlin/ Kotlin的一些特性组 ...

  3. c++中常用的泛型算法

    std中定义了很好几种顺序容器,它们自身也提供了一些操作,但是还有很多算法,容器本身没有提供. 而在algorithm头文件中,提供了许多算法,适用了大多数顺序容器.与c++11相比,很多函数在 c+ ...

  4. 窥探Swift之使用Web浏览器编译Swift代码以及Swift中的泛型

    有的小伙伴会问:博主,没有Mac怎么学Swift语言呢,我想学Swift,但前提得买个Mac.非也,非也.如果你想了解或者初步学习Swift语言的话,你可以登录这个网站:http://swiftstu ...

  5. 转载:《TypeScript 中文入门教程》 9、泛型

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性. 组件不 ...

  6. Swift—泛型(上)

    1.泛型 泛型是一种非常灵活的语法,允许程序在函数.枚举.结构体.类中定义类型形参,这种类型形参实际代表的类型是动态改变的——程序可以等到真正使用这些函数.枚举.结构体.类时才为这些类型形参传入实际的 ...

  7. C#的函数柯里化

    前面说到了C#的泛型委托和闭包函数,在函数是程序设计里还有一个重要特征是柯里化... 柯里化就是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结 ...

  8. 【C#进阶系列】12 泛型

    泛型是CLR和编程语言提供的一种特殊机制,它用于满足“算法重用”  . 可以想象一下一个只有操作的参数的数据类型不同的策略模式,完全可以用泛型来化为一个函数. 以下是它的优势: 类型安全 给泛型算法应 ...

  9. C++ find 函数用法

    头文件 #include <algorithm> 函数实现 template<class InputIterator, class T> InputIterator find ...

随机推荐

  1. Deep Learning 学习笔记(4):Logistic Regression 逻辑回归

    逻辑回归主要用于解决分类问题,在现实中有更多的运用, 正常邮件or垃圾邮件 车or行人 涨价or不涨价 用我们EE的例子就是: 高电平or低电平 同时逻辑回归也是后面神经网络到深度学习的基础. (原来 ...

  2. 第六章 MySQL函数(待续)

    ············

  3. Java中 单例(Singleton)的两种方式

    第一种(饿汉式单例模式):在声明变量时实例化 public class Singleton { //静态初始化自动实例化 private static Singleton instance = new ...

  4. leetcode592

    public class Solution { private int GCD(int a, int b) { ? GCD(b, a % b) : a; } private int LCM(int a ...

  5. Java微信公众平台开发(一)--接入微信公众平台

    转自:http://www.cuiyongzhi.com/post/38.html (一)接入流程解析 在我们的开发过程中无论如何最好的参考工具当然是我们的官方文档了:http://mp.weixin ...

  6. 玩转angularJs——通过自定义ng-model,不仅仅只是input可以实现双向数据绑定

    体验更优排版请移步原文:http://blog.kwin.wang/programming/angularJs-user-defined-ngmodel.html angularJs双向绑定特性在开发 ...

  7. 把jpg文件读取到内存char* 再转换成CImage

    网络上找到大神写的转换方法,不过就记下来,学习学习: 当然转成CImage之后就可以从CImage转换成HBITMAP 了 void DrawPic(CDC *pDC,char *buf,int le ...

  8. PHP的Enum(枚举)的实现

    转载请保留原文地址:http://www.cnblogs.com/zsxfbj/p/php_enum.html PHP其实有Enum类库的,需要安装perl扩展,所以不是php的标准扩展,因此代码的实 ...

  9. (一)maven的安装

    Maven下载 下载地址:http://maven.apache.org/download.cgi 下载完成后,得到一个压缩包

  10. Solidity string to uint

    oraclize result以string格式返回,solidity没有uint(string)这样的强制转换功能,如果要解析其中的数字,可以用oraclize提供的parseInt方法: prag ...