需要包含的头文件
#include<algorithm>
#include<numeric>
1.只读算法
find(vec.begin(),vec.end(),search_value);
accumulate(vec.begin(),vec.end(),42)
find_first_of 参数是两个迭代器参数来标记两段元素范围,在第一段范围里面查找与第二段范围中任意元素匹配的元素,然后返回一个迭代器,指向第一个匹配的元素,如果找不到则返回第一范围的end迭代器。
2.写容器元素算法
在写容器算法时必须确保算法所写的序列至少足以存储要写入的元素。
2.1 写入输入序列的元素:fill(vec.begin,vec.end(),0) 带有一对迭代器,用于指定要写入的范围,而写入的值是它的第三个形参的副本。执行时将范围内的每个元素都设为给定的值。
2.2 不检查写入操作的算法
fill_n 函数带有的参数包括:一个迭代器、一个计数器以及一个值。函数从迭代器指向的元素开始,将指定数量的元素设置为给定的值。初学者常犯的错误是:在没有元素的空容器上调用fill_n函数。此时结果未定义,很可能导致严重的运行时错误。对指定数目的元素写入运算或者写到目标迭代器的算法,都不检查目标的大小是否足以存储要写入的元素。
2.3 back_inserter函数是迭代器适配器,与容器适配器一样,迭代器使用一个对象作为实参,并生成一个适应其实参行为的新对象。在本例中,传递给back_inserter的实参是一个容器的引用。back_inserter生成一个绑定在该容器上的插入迭代器。在试图通过这个迭代器给元素赋值时,赋值运算符将调用push_back在容器中添加一个具有指定值得元素。使用back_inserter可以生成一个指向fill_n写入目标的迭代器。
vector<int> ivec;
fill_n(back_inserter(ivec),7,3);
现在fill_n函数每写入一个值,都会通过back_inserter生成的插入迭代器实现。效果相当于在vec上调用push_back,在vec尾部添加7个元素,每个元素的值都是3.
2.4 写入到目标迭代器的算法
vector<int> ivec;
copy(ilist.begin(),ilist.end(),back_inserter(ivec)); copy从输入范围内读取元素,然后将它们复制给目标ivec。
当然这个例子的效率比较差;通常如果要以一个已存在的容器为副本创建新容器,更好的方法是直接用输入范围作为新构造容器的初始化式:
vector<int> ivec(ilist.beign(),ilist.end());
2.5 算法的_copy版本
有些算法提供所谓的“复制版本”。这些算法对输入序列的元素做出处理,但不修改原来的元素,而是创建一个新序列存储元素的处理结果。
replace(ilist.begin(),ilist.end(),0,42) 把所有值为0的实例替换为42.如果不想改变原来的序列,则调用replace_copy.这个算法接收第三个迭代器实参,指定保存调整后序列的目标位置。
vector<int> ivec;
replace_copy(ilist.begin(),ilist.end(),back_inserter(ivec),0,42);
调用该函数后。ilist没有变,ivec存储ilist的一份副本,而ilist内所有的0在ivec中都变为了42.
2.6 对容器元素重新排序的算法
sort(word.begin(),word.end());按照字典排序
vector<string>::iterator iterator=unique(words.begin(),words.end());
单词排序后,使用unique“删除”了相邻的重复值,实际上是将无重复的值复制到容器前端,从而覆盖相邻的重复元素。unique返回的迭代器指向超出无重复的元素范围末端的下一个位置。
words.erase(iterator,words.end());--->删除后面剩余的值,必须使用容器来操作。
算法不直接修改容器的大小,如果需要添加或者删除元素,则必须使用容器操作。
stable_sort(words.begin(),words.end(),isShorter);对于长度相同的元素,将保留其字典顺序。
我们定义了配套的实用函数,称为谓词。是做某些检测的函数,返回用于条件判断的类型,指出条件是否成立。
vector<string>::size_type wc=count_if(words.begin(),words.end(),GT5);
2.7 再谈迭代器
1.插入迭代器
1.1 back_inserter 创建使用push_back实现插入的迭代器
1.2 front_inserter 使用push_front实现插入。
只有当容器提供push_front操作时,才能使用front_inserter。在vector或其他没有push_front运算的容器上使用front_inserter,将产生错误。
1.3 inserter 使用insert实现插入操作,除了所关联的容器外,inserter还带有第二个实参,指向插入起始位置的迭代器。
会在第二个参数所表明的元素前面插入新元素。这点类似于front_inserter。但是front_inserter的使用将导入元素以相反的次序出现在目标对象中,这点非常重要。而inserter类似于back_inserter,把要插入的数据按照原来的位置整体插入到新容器中,只是插入的位置从第二个元素前面开始。
list<int> ilist0,ilist1,ilist2;
for(int i=0;i<3;i++)
{
ilist0.push_back(i);
}
copy(ilist0.begin(),ilist0.end(),front_inserter(ilist1));
copy(ilist0.begin(),ilist0.end(),inserter(ilist2,ilist2.begin()));
ilist0 0 1 2
ilist1 2 1 0
ilist2 0 1 2
使用front_inserter,元素最终是反向的,而inserter元素是正向插入的,只是位置在第二个元素指定位置的前面。
2.iostream迭代器
istream_iterator用于读取输入流
ostream_iterator用于写输入流
3.反向迭代器
反向迭代器是一种反向遍历容器的迭代器。也就是从最后一个元素到第一个元素遍历容器。反向迭代器将自增(和自减)的含义反过来了,对于反向迭代器,++运算将访问前一个元素,--运算将访问下一个元素.
rbegin:指向容器尾部元素
rend:指向首元素前一位置的位置。
4.const迭代器
3.泛型算法的结构
容器特有的算法:与其它顺序容器所支持的操作相比,标准库为list容器定义了更精细的操作集合,使它不必只依赖于泛型操作。list容器特有的算法与其它泛型算法版本之间有两个至关重要的差别。其中一个差别是remove和unique的list版本修改了其关联的基础容器:真正删除了指定的元素。例如list::unique将list中第二个和后续重复的元素删除出该容器。与对应的泛型算法不同,list容器特有的操作能添加和删除元素。另一个差别是list容器提供的merge和splice运算会破坏 它们的实参。使用merge的泛型算法版本时,合并的序列将写入日志迭代器指向的对象,而它的两个输入序列保持不变。但是,使用list容器的merge成员函数的list对象时,实参对象的元素被移出并删除。