关键概念:算法永不执行容器提供的操作
泛型算法本身从不执行容器操作,只是单独依赖迭代器和迭代器操作实现。算法基于迭代器及其操作实现,而并非基于容器操作。使用迭代器时,算法从不修改基础容器的大小,也许会改变存储在容器中的元素的值,也许会在容器内移动元素,但是,算法从不直接添加或删除元素。
使用泛型算法必须包含algorithm头文件:
#include <algorithm>
标准库还定义了一组泛化的算术算法,其命名习惯与泛型算法相同。使用这些算法则必须包含numeric头文件:
#include <numeric>
eg:int sum = accumulate(vec.begin(),vec.end(),42);
//sum the elements in vec starting the summation with the value 42
string sum = accumulate(v.begin(),v.end(),string(""));
//concatenate elements from v and store in sum
find_first_of的使用:
这个算法带有两对迭代器参数来标记两段元素范围,在第一段范围内查找与第二段范围中任意元素匹配的元素,然后返回一个迭代器,指向第一个匹配的元素。如果找不到匹配元素,则返回第一个范围的end迭代器。
假设roster1和roster2是两个存放名字的list对象,可使用find_first_of统计有多少个名字同时出现在这两个列表中:
size_it cnt = 0;
list<string>::iterator it = roster1.begin();
while ((it = find_first_of(it,roster1.end(),roster2.begin(),roster2.end())) != roster1.end()) {
++cnt;
++it;
}
cout << "Found" << cnt << " names on both rosters "" << endl;
写入输入序列的元素:
eg:fill(vec.begin(),vec.end(),0);
fill(vec.begin(),vec.begin()+vec.size()/2,10);
不检查写入操作的算法:
fill_n函数假定对指定数量的元素做写操作是安全的。
引入back_insert
确保算法有足够的元素存储输出数据的一种方法是使用插入迭代器(insert iterator)。
#include <iterator>
eg:vector<int> vec; //empty vector
fill_n(back_inserter(vec),10,0); //appends 10 elements to vec
写入到目标迭代器的算法
eg: vector<int> ivec;
copy (ilst.begin(),ilst.end(),back_inserter(ivec));//copy从输入范围中读取元素,然后将它们复制给目标ivec。
这个例子效率比较差,如果要以一个已存在的容器为副本创建新容器,更好的方法是直接用输入范围作为新构造容器的初始化:
vector<int> ivec(ilist.begin(),ilst.end());
算法的_copy版本
replace算法对输入序列做读写操作,将序列中特定的值替换为新的值:
eg:replace(ilst.begn(),ilst.end(),0,42);//将所有值为0的实例替换成42。
如不想改变原来的序列,则调用replace_copy.
eg:vector<int> ivec;
replace_copy (ilst.begin(),ilst.end(),back_inserter(ivec),0,42);
调用该函数后,ilst没有改变,ivec存储ilst的一份副本,而ilst内所有的0在ivec中都变成了42.
对容器元素重新排序的算法
去除重复:
eg:sort(words.begin(),words.end());
//删除相邻的重复元素,然后重新排列输入范围内的元素,并返回一个迭代器,表示无重复的值范围的结束。
vector<string>::iterator end)unique = unique(words.begin(),words.end());
//删除从end_unique指向的元素开始到words的最后一个元素也删掉为止。没有得复元素的vector对象,erase也是安全的。
words.erase(end_unique,words.end());
再谈迭代器
1、插入迭代器(insert iterator):与容器绑定在一起,实现在容器中插入元素的功能。
2、iostream迭代器(iostream iterator):可与输入或输出流绑定在一起,用于迭代遍历所关联的IO流。
3、反向迭代器(reverse iterator):实现向后遍历,耍花招不是向前遍历。所有容器类型都定义了自已的reverse_iterator类型,由rbegin和rend成员函数返回。
上述迭代器类型都在iterator头文件中定义。