您的位置:首页 > 编程语言 > C语言/C++

C++ STL 常用算法

2016-10-27 21:41 357 查看
标准库定义了一组泛型算法:因为它们实现共同的操作,所以称之为“算法”;而“泛型”指的是它们可以操作在多种容器类型上,不但可作用于标准库类型,还可用在内置数组类型、甚至其他类型的序列上。大多数算法是通过遍历由两个迭代器标记的一段元素来实现其功能。使用泛型算法必须包含头文件 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 返回真的元素。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ stl 泛型 算法