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

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

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

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

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

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

◆只读算法

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

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

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

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

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

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

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

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

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

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

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

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

◆ 写容器算法

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

◆ 重排元素算法

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

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

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

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

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

● 向算法传递函数

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

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

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

// 比较函数, 用来按长度排序单词
bool isShorter(const string& s1, const string& s2){
return (s1.size() < s2.size());
}
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. TCP/IP 某些最常见的错误原因码 (errno)列表

    对于在基于 UNIX 的环境中的 TCP/IP 用户,下表列出了某些最常见的错误原因码 (errno).它不是完整的错误列表.可以在文件 /usr/include/sys/errno.h 中找到 Er ...

  2. Zooming MKMapView to fit annotation pins

    http://stackoverflow.com/questions/4680649/zooming-mkmapview-to-fit-annotation-pins - (MKCoordinateR ...

  3. Oracle性能调优

    这部分目前主要是从网上搜集来的,后续要在实践中慢慢体会. v$sqltext: 存储的是被分割的sql v$sqlarea: 存储的是完整的sql和一些统计信息,比如累计的执行次数.逻辑读.物理读等( ...

  4. poj 1742 Coins (动态规划,背包问题)

    Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 32977   Accepted: 11208 Descripti ...

  5. Spring学习笔记之BeanFactory

    Spring bean container 的根接口,也是一个bean容器的基本功能,更深一步的接口像ListableBeanFactory 和 ConfigurableBeanFactory 都是 ...

  6. 使用OCI向Oracle插入Geometry数据

    使用C/C++操作Oracle数据库,使用OCI可谓是最强大,当然也是最难的方式.Oracle是一个功能复杂而强大的数据库,它可以很好的支持空间数据(Oracle spatial).如何使用OCI向O ...

  7. 推荐可以代替Visio的HTML开发的作图工具:ProcessOn

    过去作图的时候一直都是在用visio,每一次换了电脑使用都要重新安装,这大家都知道,最头疼的就是激活问题,曾经因为激活问题我“找遍了”正个互联网,最后还没找到...从08年开始到现在,visio用了这 ...

  8. Oracle GoldenGate 12c (12.1.2.0.1) for IBM DB2 iSeries

    OGG 12.1.2.0.1 for iSeries 在2014.2.15发布,主要新增如下功能: 本地交付(Native Delivery Replicat):新功能允许用户在IBM i服务器上安装 ...

  9. solaris下的常用命令

    屏幕显示: cat输出到屏幕: more 整屏显示,b显示上一屏,f显示下一屏: head显示文件的前n行: tail显示文件的后n行: man查看命令帮助: 目录操作: 创建目录: mkdir,   ...

  10. (spring-第6回【IoC基础篇】)BeanDefinition——实例化Bean之前的第一大利器。

    上节讲了Bean实例化的内部机制,这里再复述一遍: ResourceLoader从系统中加载XML配置信息,并由Resource来表示. BeanDefinitionReader从Resource中读 ...