C++STL常用算法的使用

1.accumulate()

accumulate() 该算法作用是对区间中的元素进行累加。

int main()
{
	vector<int> v = { 1,2,3,4,5,6,7,8,9,10 };

	//普通累加法
	int sum = 0;
	for (const auto& e : v)
	{
		sum += e;
	}
	cout << "sum = " << sum << endl;

	//STL累加算法
	int sum1 = accumulate(v.begin(), v.end(), 0); //sum1 = 55 //0表示从0开始加
	cout << "sum1 = " << sum1 << endl;

	auto pos = find(v.begin(), v.end(), 6);
	int sum2 = accumulate(v.begin(), pos, 0);  //sum1 = 15;表示从开始加到pos位置的前一个数

	cout << "sum2 = " << sum2 << endl;

	return 0;
}

在这里插入图片描述

2.count()与count_if()

count()与count_if() 该算法的作用是统计区间中某个元素出现的次数。

bool isOdd(int x) //x是否为奇数
{
	return (x % 2 == 1);
}

struct Greater3  //x是否大于3
{
	bool operator()(int x)
	{
		return x > 3;
	}
};

int main()
{
	vector<int> v = { 10,20,10,20,10,10,30 };
	//按值统计 :count()
	cout << "count of 10: " << count(v.begin(), v.end(), 10) << endl;
	
	vector<int> v1 = { 1,2,3,4,5,6,7,8,9,10 };
	//根据条件统计:count_if()
	cout << "count of odd: " << count_if(v1.begin(), v1.end(), isOdd) << endl; //可以传入函数地址
	cout << "count of Greater3: " << count_if(v1.begin(), v1.end(), Greater3()) << endl; //也可以传入函数对象(仿函数,其实重载了小括号,写出来像函数)

	return 0;
}

在这里插入图片描述

注意:struct 默认的访问权限为 public,而 class 默认的访问权限为 private。

3.find()与find_if()

find()与 find_if() 该算法的作用是找元素在区间中第一次出现的位置。

struct Greater3  //x是否大于3
{
	bool operator()(int x)
	{
		return x > 3;
	}
};

int main()
{
	vector<int> v1 = { 1,2,3,4,5,6,7,8,9,10 };

	auto rit = find(v1.begin(), v1.end(), 11);	//返回值为迭代器类型
	if (rit != v1.end())
		cout << "rit = " << *rit << endl;
	else
		cout << "not find" << endl;

	//查找第一个大于3的数据
	auto rit1 = find_if(v1.begin(), v1.end(), Greater3());
	if (rit1 != v1.end())
		cout << "rit1 = " << *rit1 << endl;
	else
		cout << "not find" << endl;
	return 0;
}

在这里插入图片描述

4.merge()

merge() 该算法作用将两个有序序列合并成一个有序序列。

int main()
{
	//vector<int> v1 = { 1,3,5,7,9 };
	//vector<int> v2 = { 2,4,6,8,10 };

	//也可以将不同两个容器的值合并
	forward_list<int> v1 = { 1,3,5,7,9 };
	vector<int> v2 = { 2,4,6,8,10 };

	//可以合并到一个向量里
	//vector<int> res(v1.size() + v2.size());
	//merge(v1.begin(), v1.end(), v2.begin(), v2.end(), res.begin());
	
	//也可以合并到一个数组里
	int arr[10] = { 0 };
	//使用前提要保证两个序列有序、//O(m+n)
	merge(v1.begin(), v1.end(), v2.begin(), v2.end(), arr);

	for (const auto& e : arr)
		cout << e << " ";
	cout << endl;

	return 0;
}

在这里插入图片描述

5.partial_sort()

partial_sort() 部分排序算法 该算法的作用是:找TOPK。
partial_sort的实现原理是:对原始容器内区间为[first, middle)的元素执行make_heap()操作构造一个最大堆,然后拿[middle, last)中的每个元素和first进行比较,first内的元素为堆内的最大值。如果小于该最大值,则互换元素位置,并对[first, middle)内的元素进行调整,使其保持最大堆序。比较完之后在对[first, middle)内的元素做一次对排序sort_heap()操作,使其按增序排列。注意,堆序和增序是不同的(堆序只是保证每个根节点大于左右孩子)。因此该算法的功能实际就是:TOP - K

int main()
{
	// 找该区间中前5个最小的元素, 元素最终存储在v1的前5个位置,即只对前5哥元素进行排序
	vector<int> v1{ 4, 1, 8, 0, 5, 9, 3, 7, 2, 6 };

	//partial_sort(v1.begin(), v1.begin() + 5, v1.end()); //默认小根堆
	partial_sort(v1.begin(), v1.begin() + 5, v1.end(), greater<int>()); //仿函数:大根堆

	cout << "TOP-5: ";
	for (int i = 0; i < 5; ++i)
		cout << v1.at(i) << " "; //v1.[i]
	cout << endl;

	return 0;
}

在这里插入图片描述

6… sort() 重要

排序在实际应用中需要经常用到,而在目前的排序中,快排平均情况下是性能最好的一种排序,但是快
排也有其自身的短板,比如说:元素接近有序、元素量比较大的情况下,直接使用快排时,效率会很低。因此STL中sort算法并没有直接使用快排,而是针对各种情况进行了综合考虑。

sort函数注意:

  1. sort函数提供了两个版本
    • sort(first, last):默认按照小于方式排序,排序结果为升序,一般用排内置类型数据
    • sort(first, last, comp):可以通过comp更改元素比较方式,即可以指定排序的结果为升序或者降序,一般以仿函数对象和函数指针的方式提供.
  2. sort并不是一种排序算法,而是将多个排序算法混合而成。
  3. 当元素个数少于某一阈值时,使用直接插入排序处理。
  4. 当元素个数超过阈值时,考虑是否能用快排的方式排序,因为当元素数量达到一定程度,递归式的快排可能会导致栈溢出,此时考虑堆排序。
int main()
{
	vector<int> v1{ 4, 1, 8, 0, 5, 9, 3, 7, 2, 6 };

	//sort(v1.begin(), v1.end()); //默认小根堆,升序
	sort(v1.begin(), v1.end(), greater<int>()); //大根堆,降序

	cout << "由大到小:";
	for (const auto& e : v1)
		cout << e << " ";
	cout << endl;

	return 0;
}

在这里插入图片描述

7.partition()

partition() 该算法的作用是按照条件对区间中的元素进行划分;只负责划分不排序。

bool isOdd(int x) //x是否为奇数
{
	return (x % 2 == 1);
}

int main()
{
	vector<int> v1 = { 1,2,3,4,5,6,7,8,9,10 };

	//按照是否为奇数划分为两部分
	auto pos = partition(v1.begin(), v1.end(), isOdd);

	cout << "奇数部分:";
	for (auto it = v1.begin(); it != pos; ++it)
		cout << *it << " ";
	cout << endl;
	
	cout << "偶数部分:";
	for (auto it = pos; it != v1.end(); ++it)
		cout << *it << " ";
	cout << endl;
	return 0;
}

在这里插入图片描述

8.reverse()

reverse() 该算法的作用是对区间中的元素进行逆置。

int main()
{
	vector<int> v1 = { 1,2,3,4,5,6,7,8,9,10 };		//逆置OK
	//list<int> v1 = { 1,2,3,4,5,6,7,8,9,10 };		//逆置OK
	//set<int> v1 = { 1,2,3,4,5,6,7,8,9,10 };		//逆置error,因为reverse()会改变map/set的关键值,而map/set不允许关键值被修改

	cout << "逆置前:";
	for (const auto& e : v1)
		cout << e << " ";
	cout << endl;

	cout << "逆置后:";
	reverse(v1.begin(), v1.end());
	for (const auto& e : v1)
		cout << e << " ";
	cout << endl;

	return 0;
}

在这里插入图片描述

9.unique()

unique() 该函数的作用是删除区间中相邻的重复性元素,确保元素唯一性,注意在使用前要保证区间中的元素是有序的,才能达到真正的去重。
注意:
1. 该函数并不是将重复性的元素删除掉,而是用后面不重复的元素将前面重复的元素覆盖掉了。
2. 返回值是一个迭代器,指向的是去重后容器中不重复最后一个元素的下一个位置。
3. 该函数需要配合erase()才能真正的将元素删除掉

int main()
{
	vector<int> v1 = { 4,1,5,8,5,0,5,5,5,9,5,3,7,2,6,5 };

	cout << "删除前:";
	for (const auto& e : v1)
		cout << e << " ";
	cout << endl;

	cout << "删除后:";
	sort(v1.begin(), v1.end());
	auto it = unique(v1.begin(), v1.end());
	v1.erase(it, v1.end());
	for (const auto& e : v1)
		cout << e << " ";
	cout << endl;
	return 0;
}

在这里插入图片描述

10.next_permutation()和prev_permutation()

next_permutation是获取一个排序的下一个排列,可以遍历全排列,prev_permutation刚好相反,获取一个排列的前一个排列。
对序列 {a,b,c},每一个元素都比后面的小,按照字典序列,固定a之后,a比bc都小,c比b大,它的下一个序列即为{a,c,b},{a,c,b}的上一个序列即为{a,b,c},同理可以推出所有的六个序列为:{a,b,c}、{a,c,b}、{b,a,c}、{b,c,a}、{c,a,b}、{c,b,a},其中{a,b,c}没有上一个元素,{c,b,a}没有下一个元素。

int main()
{
	vector<int> v = { 2,1,3 };

	sort(v.begin(), v.end());	//1 2 3,所以要用后排列
	do
	{
		cout << v[0] << " " << v[1] << " " << v[2] << endl;
	} while (next_permutation(v.begin(), v.end()));

	cout << "-----------------------------" << endl;

	sort(v.begin(), v.end(), greater<int>());	//3 2 1,所以要用前排列
	do
	{
		cout << v[0] << " " << v[1] << " " << v[2] << endl;
	} while (prev_permutation(v.begin(), v.end()));

	return 0;
}

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值