C++ primer 泛型算法

find函数
使用两个迭代器和一个值调用find函数,检查两个迭代器实参标记范围内的每一个元素,如果找到返回指向该元素的迭代器,否则返回第二个迭代器实参,表示查找失败
由于find是基于迭代器的,可在任意容器中使用相同的find函数查找值,由于指针的行为和容器内的迭代器一样,也可以使用find来搜索数组
泛型算法本身从不执行容器本身的操作,只是单独的依赖迭代器和迭代器操作实现。算法基于迭代器及其操作,而非容器操作。所以算法也许会改变存储在容器中的元素的值,或者移动元素,但不会直接添加或者删除元素
使用泛型算法必须要包括 algorithm 头文件
标准库还定义了一组泛化的算数算法,使用 numeric 头文件
所有的算法都在一段范围的元素上进行操作,这个范围叫做“输出范围”,总是使用头两个形参标记该范围,分别指向要处理的第一个元素和最后一个元素的下一位置的迭代器

只读算法
只会读取其输入返回的元素,不会写这些元素,find就是,另一个简单的只读算法是 accumulate , 在 numeric 头文件中定义

写容器元素的算法
有些直接将数据写入到输入序列,有些带一个额外的迭代器参数指定写入目标,还有些将指定数目的元素写入某个序列
写入输入序列的元素
一个简单的例子就是fill函数

fill(ivec.begin(),ivec.end(),10)//在输入范围内写入
fill_n(ivec.begin(),10,0//从迭代器指向的元素开始,将指定数量的元素设定为给定的值,如果给不存在的元素设值将会带来灾难性的后果

back_inserter 函数是一个迭代器适配器,迭代器适配器使用一个对象做实参,并生成一个适应其实参行为的新对象

vector<int> ivec;
fill_n(back_inserter(ivec),10,0); //传递给back_inserter的实参是一个容器的引用,back_inserter生成一个绑定在该容器上的插入迭代器,在通过这个迭代器插入元素的时候,会调用push_back在容器中添加一个指定值的元素。使用back_inserter可以生成一个指向fill_n 写入目标的迭代器

写入到目标迭代器的算法
最简单是copy函数,带有三个参数,前两个是指定输入范围,第三个是指向目标序列的一个元素

vector<int> ivec;
copy(list.begin(),list.end(),back_inserter(ivec));

算法的_copy版本
有些算法对输入序列的元素进行处理,但不修改原来的值,而是创建一个新序列存储元素的处理结果。

replace(ivec.begin(),ivec.end(),0,42) //将所有的值为0替换成42
replace_copy(ivec.begin(),ivec.end(),back_inserter(list),0,42) //调用该函数后,ivec没有改变,list存储改变后的值

sort算法带有两个迭代器实参,指出要排序的元素范围,这个算法使用小于操作符比较元素。
unique算法,有两个指定元素范围的迭代器参数,该算法删除相邻的重复元素,然后重复排列输入范围的元素,返回一个迭代器,表示无重复的值范围的结束。
使用unique并不会改变序列的大小,也米有删除元素,只是将无重复的元素复制到前端,覆盖了前面的元素,返回的迭代器指向无重复元素范围末端的下一个位置
这里写图片描述
C++ primer 泛型算法_第1张图片

谓词是做某些检测的函数,返回用于条件判断的类型,指出条件是否成立

排序算法
sort算法,按字典次序排序
stable_sort算法,保留相等元素的原始位置,相等指的是相同的长度,有相同长度的元素还能以字典次序区分

再谈迭代器
标准库定义的迭代器不依赖于特定的容器,c++还有三种迭代器

  1. 插入迭代器,和容器绑定在一起,可以在容器中插入元素的功能
  2. iostream迭代器,这类迭代器可与输入或者输出流绑定在一起,用于迭代器所关联的io流
  3. 反向迭代器

back_inserter函数是常见一个迭代器,用来给容器添加元素。back_inserter是一个插入器,插入器是一种迭代器适配器,带有一个容器参数并生成一个迭代器,在指定容器中插入元素
c++提供了三种插入器
back_inserter:使用push_back实现插入
front_inserter:使用push_front实现插入
inserter:使用insert实现插入,除了关联的容器,inserter还有第二个参数,指向插入起始位置的迭代器,在迭代器实参表明位置前面插入新元素

iostream迭代器
流迭代器是模板,任何已定义输入操作符的类型都可以定义istream_iterator,任何已定义输出操作符的类型都可以定义ostream_iterator
C++ primer 泛型算法_第2张图片
C++ primer 泛型算法_第3张图片

流迭代器的限制
不可能从 ostream_iterator对象读入,也不可能写入到istream_iterator对象中
一旦给ostream_iterator对象赋了一个值,写入就提交了,没法修改
ostream_iterator米有 -> 操作符

反向迭代器
流迭代器不能创建反向迭代器

迭代器的种类
C++ primer 泛型算法_第4张图片

泛型算法的结构
算法的形参模式,大部分的算法采用四种形式之一:
C++ primer 泛型算法_第5张图片
alg是算法的名字,beg和end指定算法操作的元素范围,称为输入范围
带单个目标迭代器的算法
dest是一个形参,用于指定存储输出数据的目标对象,如果dest是容器上的迭代器,算法将输出内容写到容器中已经存在的元素上,更普遍的做法是,将dest和某个插入迭代器或者ostream_iterator绑定到一起。插入迭代器在容器中添加元素,确保容器有足够的空间存储输出,ostream_iterator实现写输出流功能,无需考虑元素的个数

带第二个输入序列的算法
使用beg2 和 end2 迭代器形参,指定第二个输入范围。这类算法通常将联合两个输入范围元素进行计算
只有 beg2 的将 beg2 视作第二个输入范围的首元素,但没有指定最后一个元素,这些算法假定以 beg2 开始的范围至少与 beg 和 end 指定的范围一样大

区别带有一个值或一个谓词函数参数的算法版本
算法通过检查输入范围内的元素实现一些功能,这些算法通常要用到 ==,<=等关系操作符。大部分算法还会提供第二个版本,允许程序员提供比较或测试函数取代操作符的使用
,带有谓词函数形参的使用 _if 后缀

find(ivec.begin(),ivec.end(),val) // 在ivec中查找val
find_if(ivec.begin(),ivec.end(),pred) //在ivec中查找使谓词函数返回非零值的元素

区别是否实现复制的算法版本
将元素写入到指定的输出目标,在算法名字后加 _copy 后缀

容器特有的操作,速度更快
C++ primer 泛型算法_第6张图片
C++ primer 泛型算法_第7张图片
对list对象应该优先使用list容器特有的成员版本,而不是泛型算法

你可能感兴趣的:(C++)