C++ Primer : 第十章 : 泛型算法 之 只读、写和排序算法
大多数算法都定义在<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 : 第十章 : 泛型算法 之 只读、写和排序算法的更多相关文章
- 算法学习导图+经典排序算法PHP实现
周末抽时间整理下算法,完整导图可点击下面链接获取. 点我看完整算法导图 八种排序算法的php实现 代码如下 拷贝后可直接运行 先上个运行后的图 代码:(有的自己些的 有的根据网友整理) <?ph ...
- JS写的排序算法演示
看到网上有老外写的,就拿起自已之前完成的jmgraph画图组件也写了一个.想了解jmgraph的请移步:https://github.com/jiamao/jmgraph 当前演示请查看:http:/ ...
- js算法初窥01(排序算法01-冒泡、选择、插入)
排序,我想大家一定经历过或者正在经历着.或许你不懂算法,对排序算法一无所知,但是你一定用过一些第三方库的api来一键排序,那么,在你享受便捷的同时,你是否想过它的底层是如何实现的?这样的算法实现方式是 ...
- js算法初窥02(排序算法02-归并、快速以及堆排序)
上一篇,我们讲述了一些简单的排序算法,其实说到底,在前端的职业生涯中,不涉及node.不涉及后台的情况下,我目前还真的没想到有哪些地方可以用到这些数据结构和算法,但是我在前面的文章也说过了.或许你用不 ...
- 算法和数据结构~各位排序算法的介绍与实现(C#)
排序是指将元素集合按照规定的顺序排列.通常有两种排序方法,升序排列和降序排列.例如,对整数集{5,2,7,1}进行升序排列,结果为{1,2,5,7},对其进行降序排列结果为{7,5,2,1}.总的来说 ...
- Python 一网打尽<排序算法>之从希尔排序算法的分治哲学开始
1. 前言 本文将介绍希尔排序.归并排序.基数排序(桶排序).堆排序. 在所有的排序算法中,冒泡.插入.选择属于相类似的排序算法,这类算法的共同点:通过不停地比较,再使用交换逻辑重新确定数据的位置. ...
- C++ Primer : 第十章 : 泛型算法 之 lambda表达式和bind函数
一.lambda表达式 lambda表达式原型: [capture list] (parameter list) -> retrue type { function body } 一个lambd ...
- python 下的数据结构与算法---6:6大排序算法
顶先最后推荐:哈哈,意思是放到顶部强调其重要性,但是应该我总结的六种算法看完了后再看的一篇醍醐灌顶的文章 一:冒泡排序(Bubble Sort) 原理:假设有n个数,第一轮时:从第一个元素开始,与相邻 ...
- 排序算法汇总(C/C++实现)
前言: 本人自接触算法近2年以来,在不断学习中越多地发觉各种算法中的美妙.之所以在这方面过多的投入,主要还是基于自身对高级程序设计的热爱,对数学的沉迷.回想一下,先后也曾参加过ACM大大小小的 ...
随机推荐
- 组合——Program B
CodeForces 478B Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u De ...
- 经典线程同步 关键段CS
上一篇<秒杀多线程第四篇 一个经典的多线程同步问题>提出了一个经典的多线程同步互斥问题,本篇将用关键段CRITICAL_SECTION来尝试解决这个问题. 本文首先介绍下如何使用关键段,然 ...
- JAVA每日一记
1.两个最基本的java回收算法:复制算法和标记清理算法 复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B.此为新生代最常用的算法 ...
- switch… case 语句的用法(二)
总结来说:switch的用法是判断case后面的表达式和switch后面的表达式是否相匹配,一旦case匹配,就会顺序执行后面的程序代码,而不管后面的case是否匹配,直到遇见break.都不匹配找d ...
- 打饭助手之NABC
Need: 同学们在早上跑操后要吃早饭,还有中午打饭时人更是多.常常要排很长的队伍,造成时间的浪费,和焦急的等待.因此我们需要错开打饭的高峰期,来避免打饭排队的悲哀. Approach: 通过获取摄像 ...
- LoadImage函数问题
loadimage函数加载图片类型 Value Meaning IMAGE_BITMAP Loads a bitmap. IMAGE_CURSOR Loads a cursor. IMAGE_ICON ...
- C# 展开和折叠代码的快捷键(总结)
C# 展开和折叠代码的快捷键 VS2005代码编辑器的展开和折叠代码确实很方便和实用.以下是展开代码和折叠代码所用到的快捷键,很常用: Ctrl + M + O: 折叠所有方法 Ctrl + M + ...
- unity3d基础01
Unity3d 五大视图: 1 Scene:存放hierarchy中创建的游戏对象,但实际只能看到一部分 *Scene浏览: ①右键进入“飞行模式”,方便查看整个场景 ②选中摄像机,按ALT进入浏览的 ...
- hdoj-2025
#include "stdio.h"#include "string.h"void sort(char ch[],int count[],int n,int f ...
- 极客DIY:廉价电视棒玩转GNSS-SDR,实现GPS实时定位
0×00 前言 GNSS是Global Navigation Satellite System的缩写.中文称作:全球卫星导航系统.全球导航卫星系统. GNSS泛指所有的卫星导航系统,包括全球的.区域的 ...