大多数算法都定义在<algorithm>头文件里,而标准库还在头文件<numeric>里定义了一组数值泛型算法,比如accumulate。

●  find算法,算法接受一对迭代器表示要搜寻的范围,还接受一个给定的值,算法从给定的范围内查找,返回指向第一个等于给定值的元素的迭代器,若没有找到,则返回第二个参数。

  1. int val = 5;
  2. vector<int> vec = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  3. auto find_val = find(vec.cbegin(), vec.cend(), val);
  4. cout << "The val " << val << (find_val == vec.cend() ? "is not present" : "is present") << endl;

我们不仅可以查找标准库中的元素,也可以查找内置数组中的,我们就要用到标准库的begin() 和 end()函数来获取一个数组的首迭代器和尾后迭代器。

★关键概念: 算法永远不会执行容器的操作

泛型算法本身不会执行容器的操作,它们知识运行在迭代器之上, 执行迭代器的操作。因此,这样的特性就有一个编程假定:算法不会改变容器的大小。 可能会改变容器的值,或者移动容器的元素,但永远不会添加或删除元素。 后面介绍到的一类特殊的迭代器,它们会执行容器的操作,来改变容器大小。

◆只读算法

一些算法只会读取其输入范围内的元素,而不会改变这些值,上面提到的find算法就是其中的一种。

● 只读算法  accumulate,它包含在头文件<numeric>中,它接受三个参数:前两个表示了需要求和的元素的范围,第三个表示和的初值。

accumulate的第三个值决定了函数中使用哪个加法运算符以及返回值类型。

而且,accumulate有一个编程假定:将范围里的元素加到第三个参数上的操作是可行的,这些元素类型必须和第三个参数的类型匹配,或者能转换为第三个参数值的类型。

将vector中所有的string连接起来:

  1. vector<string> v = {"Hello", "World"};
  2. string sum = accumulate(v.cbegin(), v.cend(), string(""));
  3.  
  4. // 错误,const char* 上并没与定义 + 运算符
  5. string sum = accumulate(v.cbegin(), v.cend(), "");

对于只读算法,最好使用cbegin()、cend()来避免算法改变容器元素的值。

● 只读算法  equal,用于比较两个序列中的值是否相等。 算法接受其中一个容器的一对迭代器和另一个容器的首元素。我们必须能使用 == 来比较来自两个序列的元素

如果两个容器相等,返回true,否则返回false。

equal算法基于一个非常重要的假设: 它假定第二个容器的元素至少和第一个容器一样多。 此算法要处理第一个序列中的每一个元素。

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

  1. vector<int> v1{1, 2, 3, 4, 5}
  2. vector<int> v2{1, 2, 3, 4, 6}
  3. cout << (euqal(v1.cbegin(), v1.cend(), v2.cbegin()) == true ? "euqal" : "not euqal") << endl;

◆ 写容器算法

算法fill接受一对迭代器表示要写入元素的范围,接受第三个元素表示要写入的值。

  1. fill(v1.begin(), v1.end(), 0);

算法fill_n接受三个参数: 一个迭代器表示要写入的位置,第二个参数表示要写入元素的个数,最后一个表示要写入的值

fill_n假定写入指定个数的元素是安全的。

在一个空的容器上调用fill_n,这样的行为是未定义的。

向目的位置写入数据的算法假定目的位置足够大,至少能容纳写入的元素。

算法copy把一个表示容器范围内的元素写入到目的位置,接受三个参数,前两个表示要写入元素的范围,第三个参数表示要写入的目的位置。

目的序列至少要包含和第一个序列一样多的元素,这一点很重要!

  1. int a1[] = {0, 1, 2, 3, 4, 5};
  2. int a2[sizeof(a1) / sizeof(*a1)];
  3. auto dest = copy(begin(a1), end(a1), a2);

copy返回目的位置迭代器(递增后)的值,dest恰好指向a2尾元素之后的位置。

算法replace读入一个序列,并将容器内所有等于第三个参数表示的值都改变为第四个参数所表示的值。

  1. // 将vec容器里所有值为0的元素都变为10
  2. replace(vec.begin(), vec.end(), 0, 10);

如果希望原序列保持不变,可以使用replace_copy, 此算法接受额外的第三个迭代器参数,指出调整后序列的保存位置。

  1. replace_copy(vec1.begin(), vec1.end(), back_inserter(vec2), 0, 10);

vec2是vec1的一份拷贝,只不过vec2里的元素都进行了改变。

◆ 重排元素算法

算法sort 默认使用元素类型的 < 运算符来实现排序的,它接受一对迭代器,表示要排序元素的范围。

算法unique将容器重新排序,使得不重复的元素都排在前面,接受一对迭代器表示要操作的容器范围,返回指向不重复区域之后的一个位置的迭代器。

一个消除重复单词的函数:

  1. void elimDups (vector<string>& words){
  2. sort(words.begin(), words.end());
  3. auto end_unique = unique(words.begin(), words.end());
  4. words.erase(end_unique, words.end());
  5. }

算法那paitition,接受一对迭代器和一个谓词,对容器进行划分,使得谓词为true的元素会排在容器的前面,否则排在容器后面。返回一个迭代器,指向最后一个使得谓词为true的元素之后的位置。

● 向算法传递函数

sort的第二个版本是重载过的,接受第三个参数,此参数是一个谓词

谓词是一个可调用的表达式,其返回结果是一个能用做条件的值。标准库使用的谓词分为 一元谓词(意味着只接受一个参数) 和二元谓词(接受两个参数)

接受两个参数的sort默认使用元素的 < 运算符来对元素进行排序,我们使用接受三个参数的sort时,就可以定制自己的sort

  1. // 比较函数, 用来按长度排序单词
  2. bool isShorter(const string& s1, const string& s2){
  3. return (s1.size() < s2.size());
  4. }
  5. sort(words.begin(), words.end(), isShorter);

我们就可以将单词长度来排序,如果我们还希望具有相同长度的元素按字典排序,可以使用stable_sort算法,这种未定排序算法保持相等元素的原有排序。

C++ Primer : 第十章 : 泛型算法 之 只读、写和排序算法的更多相关文章

  1. 算法学习导图+经典排序算法PHP实现

    周末抽时间整理下算法,完整导图可点击下面链接获取. 点我看完整算法导图 八种排序算法的php实现 代码如下 拷贝后可直接运行 先上个运行后的图 代码:(有的自己些的 有的根据网友整理) <?ph ...

  2. JS写的排序算法演示

    看到网上有老外写的,就拿起自已之前完成的jmgraph画图组件也写了一个.想了解jmgraph的请移步:https://github.com/jiamao/jmgraph 当前演示请查看:http:/ ...

  3. js算法初窥01(排序算法01-冒泡、选择、插入)

    排序,我想大家一定经历过或者正在经历着.或许你不懂算法,对排序算法一无所知,但是你一定用过一些第三方库的api来一键排序,那么,在你享受便捷的同时,你是否想过它的底层是如何实现的?这样的算法实现方式是 ...

  4. js算法初窥02(排序算法02-归并、快速以及堆排序)

    上一篇,我们讲述了一些简单的排序算法,其实说到底,在前端的职业生涯中,不涉及node.不涉及后台的情况下,我目前还真的没想到有哪些地方可以用到这些数据结构和算法,但是我在前面的文章也说过了.或许你用不 ...

  5. 算法和数据结构~各位排序算法的介绍与实现(C#)

    排序是指将元素集合按照规定的顺序排列.通常有两种排序方法,升序排列和降序排列.例如,对整数集{5,2,7,1}进行升序排列,结果为{1,2,5,7},对其进行降序排列结果为{7,5,2,1}.总的来说 ...

  6. Python 一网打尽<排序算法>之从希尔排序算法的分治哲学开始

    1. 前言 本文将介绍希尔排序.归并排序.基数排序(桶排序).堆排序. 在所有的排序算法中,冒泡.插入.选择属于相类似的排序算法,这类算法的共同点:通过不停地比较,再使用交换逻辑重新确定数据的位置. ...

  7. C++ Primer : 第十章 : 泛型算法 之 lambda表达式和bind函数

    一.lambda表达式 lambda表达式原型: [capture list] (parameter list) -> retrue type { function body } 一个lambd ...

  8. python 下的数据结构与算法---6:6大排序算法

    顶先最后推荐:哈哈,意思是放到顶部强调其重要性,但是应该我总结的六种算法看完了后再看的一篇醍醐灌顶的文章 一:冒泡排序(Bubble Sort) 原理:假设有n个数,第一轮时:从第一个元素开始,与相邻 ...

  9. 排序算法汇总(C/C++实现)

    前言:     本人自接触算法近2年以来,在不断学习中越多地发觉各种算法中的美妙.之所以在这方面过多的投入,主要还是基于自身对高级程序设计的热爱,对数学的沉迷.回想一下,先后也曾参加过ACM大大小小的 ...

随机推荐

  1. 一模 (4) day1

    第一题: 题目大意:给出N个人之间转账的手续X%,求出A转给B至少要多少钱才能使B得到100元.结果保留8位小数:N<=2000 解题过程: 1.很容易看出这题的图论模型,每条边的权值就是(1- ...

  2. jsp作用域

    1.page: JSP页面内所有实例的默认作用域都是page,仅限于本页面使用 2.request: 同一次请求所涉及的服务器资源(可能是页面.Servlet等),例如,程序使用<jsp:for ...

  3. CodeIgniterCodeigniter+PHPExcel导出数据到Excel文件

    解压压缩包里的Classes文件夹中的内容到application\libraries\目录下,目录结构如下:--application\libraries\PHPExcel.php--applica ...

  4. IT公司100题-14-排序数组中和为给定值的两个数字

    问题描述: 输入一个升序排序的数组,给定一个目标值target,求数组的两个数a和b,a+b=target.如果有多个组合满足这个条件,输出任意一对即可. 例如,输入升序数组[1, 3, 4, 5, ...

  5. Map学习

    1.Query Operations(查询操作) int size();boolean isEmpty(); boolean containsKey(Object key);boolean conta ...

  6. 创建条形码图像易用的控制字符编码功能的条形码控件Native Crystal Reports Barcode Generator

    Native Crystal Reports Barcode Generator是一个对象,它可以很容易地被嵌入到一个Crystal Report中用于创建条形码图像.一旦此条形码被安装在一个报表中, ...

  7. self.view 的不当操作造成死循环

    如题,在创建ContentView的时候,例子如下 NSString *viewClassName = NSStringFromClass([self class]); viewClassName = ...

  8. MVC的传递数据的方法

    1.使用ViewBag #region 0.2 Action方法 + ActionResult Index2() /// <summary> /// Action方法 /// </s ...

  9. Hash(哈希)

    一.基本概念 Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的 ...

  10. Form表单的操作

    form对象 <form name=“form1” action=“login.php” method=“post”></form> form对象的属性 name:表单名称 m ...