标准库定义了一组泛型算法:因为它们实现共同的操作,所以称之为“算法”;而“泛型”指的是它们可以操作在多种容器类型上,不但可作用于标准库
类型,还可用在内置数组类型、甚至其他类型的序列上。大多数算法是通过遍历由两个迭代器标记的一段元素来实现其功能。使用泛型算法必须包含头
文件 algorithm :
#include <algorithm>
标准库还定义了一组泛化的算术算法(generalized numeric algorithm),其命名习惯与泛型算法相同。使用这些算法则必须包numeric头文件:
#include <numeric>
区别带一个函数参数的算法版本:大部分算法会提供比较或测试函数取代操作符使用的版本,此版本在名字中加了 _if 后缀。
区别是否实现复制的算法版本:很多算法将重新排列的元素写回其输入范围。标准库提供了复制版本,此版本的算法在名字中添加了 _copy 后缀。
迭代器实参类型
通常泛型算法都是在标记容器(或其他序列)内的元素范围的迭代器上操作的。标记范围的两个实参类型必须精确匹配,它们必须指向同一个容器中的
元素(或者超出容器末端的下一位置),并且如果两者不相等,则第一个迭代器通过不断地自增,必须可以到达第二个迭代器。对于带有两对迭代器参
数的算法,如find_first_of:每对迭代器中,两个实参的类型必须精确匹配,但不要求两对之间的类型匹配。特别是,元素可存储在不同类型序列中,
只要这两序列的元素可以比较即可。
一、只读算法
查找算法
find_if( beg, end, func ) :函数find 的带一个函数参数的 _if 版本,与 find 功能相同,条件:使函数 func 返回true。
搜索与统计算法
count_if( beg, end, func ):函数count 的 _if 版本。
#include <vector> #include <algorithm> #include <iostream> using namespace std; bool evenNum( int n ) //是否为偶数 { return n % 2; } void main() { int num = 6; vector<int> v1; for( int i = 0; i != 10; ++i ) v1.push_back(i); vector<int>::iterator iter = find( v1.begin(), v1.end(), num ); //查找等于6的元素位置 if( iter != v1.end() ) cout << "匹配元素的索引: " << iter - v1.begin() << endl; //找到匹配元素位置6 vector<int> v2; v2.push_back(6); v2.push_back(5); v2.push_back(3); iter = find_first_of( v1.begin(), v1.end(), v2.begin(), v2.end() ); //第一个匹配元素是3 if( iter != v1.end() ) cout << "第一个匹配元素索引:" << iter - v1.begin() << endl; int even_times = count_if( v1.begin(), v1.end(), evenNum ); //谓词函数参数,偶数个数为5个 cout << "偶数个数 :" << even_times << endl; vector<int> v3; v3.push_back(1); v3.push_back(1); v3.push_back(2); v3.push_back(2); //v3 非递减,每次循环 iter 跳向第一个大于当前元素的位置,因此只输出两个数 1,2 for( iter = v3.begin(); iter != v3.end(); iter = lower_bound( iter, v3.end(), *iter ) ) cout << *iter << " "; }
二、可变序列算法
可变序列算法包括元素复制、变换、替换、填充、移除和随机生成等。
copy,transform,fill_n 和 generat 都需要保证:输出序列有足够的空间。
remove函数并不真正删除元素,只是将要删除的元素移动到容器的末尾,删除元素需要容器 erase 函数来操作。同理,unique 函数也不会改变容器的
大小,只是这些元素的顺序改变了,是将无重复的元素复制到序列的前端,从而覆盖相邻的重复元素。unique 返回的迭代器指向超出无重复的元素范
围末端的下一位置。
remove_if( beg, end, func ):remove 的 _if 版本。
replace_if( beg, end, func, v2 ):replace 的 _if 版本。
_copy 版本,需注意:必须保证输出序列的大小不小于输入序列的大小。
remove_copy( beg, end, dest ):remove 的 _copy 版本,将反转后的序列输出到从dest 开始的区间。
remove_copy_if( beg, end, dest, func ):remove_copy 的 _if 版本。
replace_copy( beg, end, dest, v1, v2) :replace 的 _copy 版本。
replace_copy_if( beg, end, dest, func, v2 ):replace_copy 的 _if 版本。
三、排序算法
partial_sort 对区间 [beg, end) 内的 mid - beg 个元素进行排序,将最小的 mid - beg 个元素有序放在序列的前 mid - beg 的位置上。
reverse_copy( beg, end, dest ):reverse 的 _copy 版本。
rotate_copy (beg, mid, end, dest):rotate 的 _copy 版本。
四、关系算法
标准库还提供 求最大值、最小值的 max 和 min 函数。
五、堆算法
vector<int> v; v.push_back(3); v.push_back(9); v.push_back(17); v.push_back(20); v.push_back(12); make_heap(v.begin(),v.end()); //用 vector 代替数组建立最大堆 cout << "堆: "; for( vector<int>::iterator iter= v.begin(); iter != v.end(); ++iter ) cout << *iter << " "; cout<<endl; cout << "堆排序后: "; sort_heap(v.begin(),v.end()); //堆排序 for( vector<int>::iterator iter = v.begin(); iter != v.end(); ++iter ) cout << *iter << " "; cout<<endl;
容器特有的算法
list 容器上的迭代器是双向的,而不是随机访问类型。因此,在此容器上不能使用需要随机访问迭代器的算法。这些算法包括 sort 及其相关的算法。还
有一些其他的泛型算法,如 merge、remove、reverse 和 unique,虽然可以用在list 上,但却付出了性能上的代价。如果这些算法利用 list 容器实现的
特点,则可以更高效地执行。
标准库为 list 容器定义了更精细的操作集合,使它不必只依赖于泛型操作。
lst.remove_if(func):remove() 的 _if 版本,删除使func 返回真的元素。