C++ 常用算法(STL)

亦可参考:C++ STL常用算法(排序、合并、搜索和分区)

标准库定义了一组泛型算法:因为它们实现共同的操作,所以称之为“算法”;而“泛型”指的是它们可以操作在多种容器类型上,不但可作用于标准库类型,还可用在内置数组类型,甚至其他类型的序列上大多数算法是通过遍历由两个迭代器标记的一段元素来实现其功能使用泛型算法必须包含头文件算法。:

#include <algorithm>

标准库还定义了一组泛化的算术算法(generalized numeric algorithm),其命名习惯与泛型算法相同。使用这些算法则必须包数字头文件:

   #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都需要保证:输出序列有足够的空间。

删除函数并不真正删除元素,只是将要删除的元素移动到容器的末尾,删除元素需要容器擦除函数来操作。同理,独特的函数也不会改变容器的大小,只是这些元素的顺序改变了,是将无重复的元素复制到序列的前端,从而覆盖相邻的重复元素.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版本。

class A
{
public:
	bool operator()(int i, int j)
	{
		return i > j;
	}
};
int main()
{
	vector<int> vec{ 12, 2, 6, 1, 8 };
	A a;
	sort(vec.begin(), vec.end(), a);

	for (const auto& it : vec)
	{
		cout << it << endl;
	}
	return 0;
}

四、关系算法

在这里插入图片描述

标准库还提供求最大值,最小值的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及其相关的算法。还有一些其他的泛型算法,如合并,删除,反向和唯一,虽然可以用在列上,但却付出了性能上的代价。如果这些算法利用列表容器实现的特点,则可以更高效地执行。

标准库为list容器定义了更精细的操作集合,使它不必只依赖于泛型操作。

在这里插入图片描述

lst.remove_if(func):remove()的_if版本,删除使用func返回真的元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值