C++STL常用算法学习(一)

本文主要参考博客:1.https://www.cnblogs.com/linuxAndMcu/p/10264339.html

                                 2.https://blog.csdn.net/xyqqwer/article/details/81263060

                                3.https://www.cnblogs.com/larry-xia/p/9497340.html

                                4.https://blog.csdn.net/vocaloid01/article/details/80583539

                                5.https://blog.csdn.net/shudaqi2010/article/details/22985303

                                6.https://www.cnblogs.com/DswCnblog/p/5629165.html

STL算法部分主要由头文件 <algorithm>,<numeric>,<functional> 组成。要使用 STL中的算法函数必须包含头文件 <algorithm>,对于数值算法须包含 <numeric>,<functional> 中则定义了一些模板类,用来声明函数对象。

STL 中算法大致分为四类:

  • 非可变序列算法(只读算法):指不直接修改其所操作的容器内容的算法。包括查找算法:常用的有find、find_first_of、find_end、find_if、find_if_not(c++11开始)、adjacent_find、any_of(c++11)、all_of(c++11)、none_of(c++11);搜索与统计算法search、search_n、count、count_if、lower_bound、upper_bound、equal_range。关系算法:min_element、max_elememt、minmax_element、equal、includes、mismatch
  • 可变序列算法:指可以修改它们所操作的容器内容的算法。包括元素复制、变换、替换、填充、移除和随机生成等。更易型算法:copy、replace、replace_if、fill、fill_n、generate、generate_n、replace_copy、replace_copy_if、swap、swap_ranges、transform、move(c++11)、reverse、reverse_copy、rotate、rotate_copy;移除型算法remove、unique、remove_if、unique_copy、remove_copy、remove_copy_if
  • 排序及相关算法:包括对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作。排序算法:sort、stable_sort、partial_sort、partial_sort_copy、make_heap、push_heap、pop_heap、sort_heap;合并算法:merge、inplace_merge;排列:is_permutation(c++11)、next_permutation、prev_permutation、random_shuffle、shuffle(c++11)、partition、stable_partition、partition_copy ;检验是否排序算法:is_sorted(c++11)、is_sorted_until(c++11)、is_partitioned(c++11)、partition_point(c++11)、is_heap(c++11)、is_heap_until(c++11);已排序区间算法:binary_search();集合算法iset_union、set_intersection、set_difference、set_symmetric_difference
  • 数值算法:对容器内容进行数值计算。accumulate、inner_product、adjacent_difference、partial_sum、iota函数

目录

 

一、非可变序列算法

1.1 查找算法

find:  

find_first_of:

find_end:

find_if:

find_if_not:

adjacent_find:

all_of:

none_of:

any_of:

代码验证:

运行结果:

1.2 搜索与统计算法

search:

search_n:

count:

count_if:

lower_bound:

upper_bound:

equal_range:

代码验证:

运行结果:

1.3关系算法

min_element:

max_element:

minmax_element:

equal:

includes:

mismatch:

代码验证

运行结果:

 


一、非可变序列算法

1.1 查找算法

find:  

find(begin,end,value); 它的输入查找范围参数都是指针或是迭代器,返回的也是指针或是迭代器:在[begin,end)内查找等于value的元素,找到则返回对应的迭代器,否则返回end。

find_first_of:

find_first_of(begin,end,begin2,end2);在迭代区间[begin,end)查找与区间[beg2,end2)内任意元素匹配的元素,然后返回一个迭代器,指向第一个匹配的元素。如果找不到元素,则返回第一个范围的end迭代器。

find_end:

find_end(begin,end,begin2,end2);查找[begin2,end2)子区间在区间[begin,end)最后一次出现的位置

注意:find_frist_of与find_end有很大的差别

find_if:

find_if(beg,end,func):函数find的带一个函数参数的_if版本,与find功能相同,条件:使函数func返回true。返回满足该条件的第一个元素的迭代器。

find_if_not:

与find_if相反,返回不符合条件的第一个元素的迭代器。

adjacent_find:

查找连续两个相等(或者说符合特定准则)的元素;其有两种函数原型:1、在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的ForwardIterator。2、另一种是使用二元谓词判断binary_pred,查找迭代器区间 [first , last)上满足binary_pred条件的邻近元素对,未找到则返回last。

all_of:

all_of(beg,end,func):在[beg,end)这个区间,所有的元素都满足func,则返回true;

none_of:

none_of(beg,end,func):在[beg,end)这个区间,所有元素都不满足func,则返回true;

any_of:

any_of(beg,end,func):在[beg,end)这个区间,判断是否由一个元素满足func,有则返回true

会涉及到lambda表达式,此处对lambda表达式也做简单的介绍:

Lambda表达式完整的声明格式如下:

[capture list] (params list) mutable exception-> return type { function body }

各项具体含义如下:

capture list:捕获外部变量列表
params list:形参列表
mutable指示符:用来说用是否可以修改捕获的变量
exception:异常设定
return type:返回类型
function body:函数体

还有一些缺省的表达式:
1.[capture list] (params list) -> return type {function body}
2.[capture list] (params list) {function body}
3.[capture list] {function body}

格式1声明了const类型的表达式,这种类型的表达式不能修改捕获列表中的值。
格式2省略了返回值类型,但编译器可以根据以下规则推断出Lambda表达式的返回类型: (1):如果function body中存在return语句,则该Lambda表达式的返回类型由return语句的返回类型确定; (2):如果function body中没有return语句,则返回值为void类型。
格式3中省略了参数列表,类似普通函数中的无参函数。

代码验证:

#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>

using namespace std;

bool divbyfive(int x)
{
	return x % 5 ? 0:1;
}
bool adjdiff(int x, int y)
{
	return x - y== -2 ? 1 : 0;
}

bool judgeeven(int x)
{
	return x % 2==0?1:0;
}

int main()
{
	vector<int> vectest0 = { 2,3,4,2,3,4 };
	vector<int> vectest = { 1,2,3,4,5,6 };
	vector<int> vectest2 = { 5,7,4,9 };
	vector<int> vectest3 = { 2,3,4 };
	vector<int> vectest4 = { 1,2,2,4,5,5,7 };
    vector<int> vectest5 = { 2,4,6,8 };
	vector<int> vectest6 = { 1,3,5,7 };

	int num = 5;

	//find
	vector<int>::iterator vectest_iter = find(vectest.begin(), vectest.end(), num);
	if (vectest_iter != vectest.end())//查找成功 输出位置
	{
		cout << "匹配元素的索引为:" << vectest_iter - vectest.begin() << endl;
		cout << "迭代器指向的值:" << *vectest_iter << endl;
	}

	//find_first_of
	vector<int>::iterator vectest_iter2 = find_first_of(vectest.begin(), vectest.end(), vectest2.begin(), vectest2.end());
	if (vectest_iter2!= vectest.end())//vectest中存在与vectest2相同的元素
	{
		cout << "第一个匹配元素的索引为:" << vectest_iter2 - vectest.begin() << endl;
		cout <<"迭代器指向的值:"<< *vectest_iter2 << endl;//输出找到的值
	}

	//find_end

	vector<int>::iterator vectest_iter3 = find_end(vectest0.begin(), vectest0.end(), vectest3.begin(), vectest3.end());
	if (vectest_iter3 != vectest0.end())//vectest中存在与vectest2相同的元素
	{
		cout << "区间最后匹配的索引为:" << vectest_iter3 - vectest0.begin() << endl;
		cout <<"迭代器指向的值:"<< *vectest_iter3 << endl;//输出找到的值
	}

	//find_if
	vector<int>::iterator vectest_iter4 = find_if(vectest.begin(), vectest.end(), divbyfive);
	if (vectest_iter4 != vectest.end())
	{
		cout << "第一个符合条件的索引为:" << vectest_iter4 - vectest.begin() << endl;
		cout <<"迭代器指向的值:"<< *vectest_iter4 << endl;//输出找到的值
	}
	vector<int>::iterator vectest_iter5 = find_if(vectest.begin(), vectest.end(), bind2nd(greater<int>(), 2));
	//顺带学习bind2nd于bing1st函数,这两是绑定函数
	//bind1st(const Operation& op, const T& x)
	//bind2nd(const Operation& op, const T& x)
    //bind1st函数代表这么一个操作:  x op value;      bind2nd函数代表:value op x。
	//那么bind2nd(greater<int>(), 2)就是vectest中大于2的值
	if (vectest_iter5 != vectest.end())
	{
		cout << "第一个符合条件的索引为:" << vectest_iter5 - vectest.begin() << endl;
		cout <<"迭代器指向的值:"<< *vectest_iter5 << endl;//输出找到的值
	}
	//find_if_not
	vector<int>::iterator vectest_iter6 = find_if_not(vectest.begin(), vectest.end(), bind2nd(greater<int>(), 2));
	if (vectest_iter6 != vectest.end())
	{
		cout << "第一个不符合条件的索引为:" << vectest_iter6 - vectest.begin() << endl;
		cout <<"迭代器指向的值:"<< *vectest_iter6 << endl;//输出找到的值
	}
	//adjacent_find
	vector<int>::iterator vectest_iter7 = adjacent_find(vectest4.begin(), vectest4.end());
	if (vectest_iter7 != vectest4.end())
	{
		cout << "第一对相等邻近元素的第一个位置:" << vectest_iter7 - vectest4.begin() << endl;
		cout <<"邻近值对儿:"<< *vectest_iter7<<'\t'<< *vectest_iter7++ << endl;//输出找到的值
	}
	vector<int>::iterator vectest_iter8 = adjacent_find(vectest4.begin(), vectest4.end(), adjdiff);
	if (vectest_iter8 != vectest4.end())
	{
		cout << "第一对邻近元素差为2的第一个位置:" << vectest_iter8 - vectest4.begin() << endl;
		cout << "符合条件的邻近对儿:" << *vectest_iter8 << '\t' << *vectest_iter8++ << endl;//输出找到的值
	}

	//any_of
	bool anytest = any_of(vectest3.begin(),vectest3.end(),judgeeven);
	
	if (anytest)
	{
		cout << "该序列存在偶数" << endl;
	}
	//all_of
	//bool alltest = all_of(vectest5.begin(), vectest5.end(), judgeeven);
	//或者使用lambda表达式
	bool alltest = all_of(vectest5.begin(), vectest5.end(), [](int i)-> bool{return(i % 2 == 0); });
	if (alltest)
	{
		cout << "该序列均为偶数" << endl;
	}
	//none_of
	bool nonetest = none_of(vectest6.begin(), vectest6.end(), judgeeven);
	if (nonetest)
	{
		cout << "该序列没有偶数" << endl;
	}
	system("pause");
	return 0;
}

运行结果:

1.2 搜索与统计算法

search:

search(beg,end,beg2,end2),在区间[beg,end)内查找子序列[beg2,end2)该函数与find_end用法上对应,给出两个范围,返回一个ForwardIterator,查找成功指向第一个范围内第一次出现子序列(第二个范围)的位置,查找失败指向end。

search_n:

search(beg,end,n,v)或search(beg,end,n,v,binary_pred),在区间[beg,end)内查找连续n个元素v或者满足谓词判断binary_pred的条件(在区间[beg,end)内查找连续n个使用binary_pred之后满足值为v的),返回子序列首元素的迭代器,或end以表示没有重复元素的子序列。

count:

count(beg,end,v)利用等于操作符,把标志范围内[beg,end)的元素与输入值v比较,返回相等元素个数。

count_if:

count_if(beg,end,func)利用输入的操作符,对标志范围内[beg,end)的元素进行操作,返回func结果为true的个数。

lower_bound:

lower_bound(beg,end,v),在非递减序列[beg,end)内第一个大于或等于v的位置,找到则返回迭代器,没找到则等于end。使用二分查找找到位置

upper_bound:

upper_bound(beg,end,v),在非递减序列[beg,end)内第一个大于v的元素的位置,找到则返回迭代器,没找到则等于end。使用二分查找找到位置

(该图像来源于参考博客4,感觉很形象,搬过来有助于理解,如有侵权,望联系笔者删除)

equal_range:

返回等于某个给定值的所有元素构成的区间。返回的区间由pair表示,pair的first刚好为lower_bound计算出的迭代器,pair的second刚好为upper_bound计算出的迭代器具体的说是一种二分查找的算法,试图在已排序的[beg,end)中寻找value,它返回一对迭代器i和j,其中i是在不破坏次序的前提下,value可插入的第一个位置(亦即lower_bound),j则是在不破坏次序的前提下,value可插入的最后一个位置(亦即upper_bound),因此,[i,j)内的每个元素都等同于value,而且[i,j)是[beg,end)之中符合此一性质的最大子区间,   如果以稍许不同的角度来思考 equal_range,我们可把它想成是[beg,end)内"与value等同"之所有元素形成的区间A,由于[fist,last)有序(sorted),所以我们知道"与value等同"之所有元素一定都相邻,于是, 算法lower_bound返回区间A的第一个迭代器, 算法upper_bound返回区间A的最后一个元素的下一个位置,算法equal_range则是以pair的形式将两者都返回,即使[beg,end)并未含有"与value等同"之任何元素,以上叙述仍然合理,这种情况下,"与value等同"之所有元素形成的,其实是一个空区间,在不破坏次序的情况下,只有一个位置可以插入value,而equal_range所返回的pair,其第一和第二(都是迭代器)皆指向该位置。

代码验证:

#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>

using namespace std;

 bool twice(const int para1, const int para2)
{
	return 2 * para1 == para2;
}
int main()
{
	vector<int> vectest0 = { 2,3,4,2,3,4 };
	vector<int> vectest = { 1,2,3,4,5,6 };
	vector<int> vectest2 = { 5,7,4,9 };
	vector<int> vectest3 = { 2,3,4 };
	vector<int> vectest4 = { 1,2,2,4,5,5,7 };


	//search
	vector<int>::iterator vectest_iter9 = search(vectest0.begin(), vectest0.end(), vectest3.begin(), vectest3.end());
	if (vectest_iter9 != vectest0.end())//vectest中存在与vectest2相同的元素
	{
		cout << "搜索区间第一匹配的索引为:" << vectest_iter9 - vectest0.begin() << endl;
		cout << "迭代器指向的值:" << *vectest_iter9 << endl;//输出找到的值
	}

	//search_n
	vector<int>::iterator vectest_iter10 = search_n(vectest4.begin(), vectest4.end(),2 ,5 );
	if (vectest_iter10!= vectest4.end())//在vectest4中能够查找到两个5
	{
		cout << "查找到的第一个两个5的索引为:" << vectest_iter10 - vectest4.begin() << endl;
		cout << "迭代器指向的值:" << *vectest_iter10 << endl;//输出找到的值
	}
	vector<int>::iterator vectest_iter11 = search_n(vectest4.begin(), vectest4.end(), 2, 4, twice);
	if (vectest_iter11 != vectest4.end())//在vectest4中能够查找到两个5
	{
		cout << "查找到的第一个2个连续的twice之后的值为4的:" << vectest_iter11 - vectest4.begin() << endl;
		cout << "迭代器指向的值:" << *vectest_iter11<< endl;//输出找到的值
	}

	//count
	int number = count(vectest4.begin(), vectest4.end(), 2);
    cout << "vectest4中2的数量:" <<number << endl;

	//count_if
	int number2 = count_if(vectest4.begin(), vectest4.end(), bind2nd(greater<int>(),2));
	cout << "vectest4中大于2的数量:" << number2 << endl;

	//lower_bound
	vector<int>::iterator vectest_iter12 = lower_bound(vectest4.begin(), vectest4.end(), 2);
	if (vectest_iter12 != vectest4.end())//在vectest4中能够查找到两个5
	{
		cout << "找到的lower_bound位置是:" << vectest_iter12 - vectest4.begin() << endl;
		cout << "迭代器指向的值:" << *vectest_iter12 << endl;//输出找到的值
	}

	//upper_bound
	vector<int>::iterator vectest_iter13 = upper_bound(vectest4.begin(), vectest4.end(), 2);
	if (vectest_iter13 != vectest4.end())//在vectest4中能够查找到两个5
	{
		cout << "找到的upper_bound位置是:" << vectest_iter13 - vectest4.begin() << endl;
		cout << "迭代器指向的值:" << *vectest_iter13 << endl;//输出找到的值
	}

	//equal_range
	pair<vector<int>::iterator, vector<int>::iterator> range;
	range = equal_range(vectest4.begin(), vectest4.end(),2);
	cout << range.first-vectest4.begin() << '\t' << range.second - vectest4.begin() << endl;

	system("pause");
	return 0;
}

运行结果:

1.3关系算法

min_element:

min_element(beg,end),返回[beg,end)范围内最小元素的迭代器.

max_element:

max_element(beg,end),返回[beg,end)范围内最大元素的迭代器

注意:它们与min以及max的区别,min与max是两个值比较,且结果直接是值,而上边的两个是迭代器(地址)

minmax_element:

minmax_element(beg,end),该函数是返回指定范围内[beg,end)的最大最小值的元素的迭代器组成的一个pair, 如果最值多于一个, firstf返回的是第一个出现的最小值的迭代器,second返回的是最后一个出现的最大值的迭代器 。

equal:

equal(beg,end,beg2,end2)如果两个序列在标志范围内元素都相等,返回true

includes:

includes(beg,end,beg2,end2)判断第一个指定范围内[beg,end)的所有元素是否包含第二个范围[beg2,end2),成功返回true

mismatch:

mismatch(beg,end,beg2)查找两个序列中第一个不匹配的元素返回一对迭代器,标记第一个不匹配元素的位置。

代码验证

#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>
#include <math.h>

using namespace std;

int main()
{
	vector<int> vectest0 = { 2,3,4,2,3,4 };
	vector<int> vectest = { 1,2,3,4,5,6 };
	vector<int> vectest2 = { 5,7,4,9 };
	vector<int> vectest3 = { 2,3,4 };
	vector<int> vectest4 = { 1,2,2,4,5,5,7 };


    //min_element
     vector<int>::iterator vectest_iter14 = min_element(vectest4.begin(), vectest4.end());
	 if (vectest_iter14 != vectest4.end())//在vectest4中能够查找到两个5
	 {
	 	cout << "最小值的位置是:" << vectest_iter14 - vectest4.begin() << endl;
	 	cout << "最小值:" << *vectest_iter14 << endl;//输出找到的值
	 }
	 //min
	 int a = 10, b = 15;
	 cout << min(a, b) << endl;
   
    //max_element
	 vector<int>::iterator vectest_iter15 = max_element(vectest4.begin(), vectest4.end());
	 if (vectest_iter15 != vectest4.end())//在vectest4中能够查找到两个5
	 {
		 cout << "最大值的位置是:" << vectest_iter15 - vectest4.begin() << endl;
		 cout << "最大值:" << *vectest_iter15 << endl;//输出找到的值
	 }
	 //max
	 cout << max(a, b) << endl;
    
    //minmax_element
	 //auto vectest_iter16 = minmax_element(vectest4.begin(), vectest4.end());
	 pair<vector<int>::iterator, vector<int>::iterator> vectest_iter16 = minmax_element(vectest4.begin(), vectest4.end());
	 cout <<"最小值:"<< *vectest_iter16.first << " ,最大值=" << *vectest_iter16.second << endl;

	 //字符串截取
	 vector<int>::iterator i1 = vectest.begin() + 1, i2 = vectest.begin() + 4;
	 vector<int> vectestsub(i1, i2);
	 //equal
	 bool equalflag = equal(vectestsub.begin(), vectestsub.end(), vectest3.begin(), vectest3.end());
	 if (equalflag)
	 {
		 cout << "两个序列元素相同" << endl;
	 }
	 //includes
	 bool includesflag = includes(vectest.begin(), vectest.end(), vectestsub.begin(), vectestsub.end());
	 if (includesflag)
	 {
		cout << "前边序列包含后边序列" << endl;
	 }

	 //mismatch
	 auto vectest_iter17 = mismatch(vectest.begin(),vectest.end(),vectest4.begin());
	 cout << "第一组不相等元素:" << *vectest_iter17.first << '\t' << *vectest_iter17.second << endl;

	system("pause");
	return 0;
}

运行结果:

 

 

下一博客将总结对可变序列算法的学习总结。

        

文中若有不妥或错误之处,还望指出。

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值