【学习篇】【C++】【STL-常用算法】

本文详细介绍了STL中的常见算法,包括遍历算法如for_each和transform,查找算法find、find_if及adjacent_find,排序算法sort、random_shuffle等,拷贝和替换算法如copy、replace、replace_if,以及算术生成和集合算法。通过实例演示了每个算法的使用方法和注意事项,帮助读者深入理解STL算法的运用。
摘要由CSDN通过智能技术生成

算法主要是由头文件< algorithm >< functional >< numeric >组成

  • < algorithm >是所有STL头文件中最大的一个
  • < numeric >体积很小,只包括了几个在序列上面进行简单数学运算的模板函数
  • < functional >定义了一些模板类,用以声明函数对象

一、遍历算法

1. for_each

函数原型解释
for_each(iterator begin, iterator end, func);实现遍历容器

begin:开始迭代器
end:结束迭代器
func:函数or函数对象

vector<int>v;
for_each(v.begin(), v.end(), print01); //放的是普通函数print01()

for_each(v.begin(), v.end(), print02());  //放的是仿函数print02()

2. transform

函数原型解释
transform(iterator begin1, iterator end1, iterator begin2, func);搬运容器到另一个容器中

begin1:源容器开始迭代器
end1:源容器结束迭代器
begin2:目标容器开始迭代器
func:函数or函数对象(在搬运期间可以做一些操作)

注意: 目标容器需要提前开辟空间

class Trans
{
public:
	int operator ()(int val)
	{
		return val + 10;
	}
};
void test01()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	
	vector<int>vTarget; //目标容器
	vTarget.resize(v.size()); //目标容器需要提前开辟空间

	transform(v.begin(), v.end(), vTarget.begin(), Trans());
}

二、查找算法

1. find

函数原型解释
find(iterator begin, iterator end, value);查找指定元素,找到返回指定元素的迭代器,找不到返回结束迭代器end()

begin:开始迭代器
end:结束迭代器
value:查找的元素
返回值是迭代器

void test01()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	//返回的是迭代器
	vector<int>::iterator pos = find(v.begin(), v.end(), 50); 
	if (pos == v.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了" << *pos << endl;
	}
}

在查找自定义数据类型时,需要重载==号,否则底层不知道怎么对比数据是否为要查找的。

class Person
{
public:
	string m_name;
	int m_age;
public:
	Person(string name, int age)
	{
		this->m_name = name;
		this->m_age = age;
	}
	bool operator==(const Person& p)
	{
		if (this->m_name == p.m_name && this->m_age == p.m_age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
};

void test02()
{
	vector<Person>v;
	//创建并添加Person的数据
	Person p1("aaa", 10);Person p2("bbb", 20);
	Person p3("ccc", 30);Person p4("ddd", 40);
	v.push_back(p1);v.push_back(p2);
	v.push_back(p3);v.push_back(p4);
	
	//返回的是迭代器
	vector<Person>::iterator Personpos = find(v.begin(), v.end(), p2); 
	if (Personpos == v.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了,姓名为:" << Personpos->m_name
			<< " 年龄为:" << Personpos->m_age
			<< endl;
	}
}

2. find_if

函数原型解释
find_if(iterator begin, iterator end, _Pred);按值查找元素,找到返回指定元素的迭代器,找不到返回结束迭代器end()

begin:开始迭代器
end:结束迭代器
_Pred:函数或谓词(返回bool类型的仿函数)
返回值是迭代器

举例:

  1. 找到大于5的数字
class greaterfive
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};
void test01()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	
	//返回的是迭代器
	vector<int>::iterator pos = find_if(v.begin(), v.end(), greaterfive()); 
	if (pos == v.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了大于5的数字:" << *pos << endl;
	}
}
  1. 找到年龄大于20的数据(自定义数据类型),记得需要重载==号
class agegreater20
{
public:
	bool operator()(const Person& p)
	{
		return p.m_age > 20;
	}
};
void test02()
{
	vector<Person>v;
	//创建并添加Person的数据
	Person p1("aaa", 10);Person p2("bbb", 20);
	Person p3("ccc", 30);Person p4("ddd", 40);
	v.push_back(p1);v.push_back(p2);
	v.push_back(p3);v.push_back(p4);

	//返回的是迭代器
	vector<Person>::iterator it = find_if(v.begin(), v.end(), agegreater20()); 
	if (it == v.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了,姓名为:" << it->m_name
			<< " 年龄为:" << it->m_age
			<< endl;
	}
}

3. adjacent_find

查找相邻重复元素

函数原型解释
adjacent_find(iterator begin, iterator end);查找相邻重复元素,返回相邻元素的第一个位置的迭代器

begin:开始迭代器
end:结束迭代器
返回值是迭代器

4. binary_search

二分查找法,查找指定元素是否存在

函数原型解释
bool binary_search(iterator begin, iterator end, value);查找指定元素,查到返回true,否则false

begin:开始迭代器
end:结束迭代器
value:查找的元素

注意: 虽然二分查找法的效率很高,但是在无序序列中不可用,结果为未知

5. cout

统计元素个数

函数原型解释
cout(iterator begin, iterator end, value);统计元素个数

begin:开始迭代器
end:结束迭代器
value:统计的元素

举例:

  1. 统计内置的数据类型
void test01()
{
	vector<int>v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(2);
	v.push_back(4);
	
	int num = count(v.begin(), v.end(), 2); 
	cout << "2的个数为:" << num << endl;
  1. 统计自定义的数据类型

在统计自定义数据类型时,需要重载==号,否则底层不知道怎么对比数据是否为要统计的。

class Person
{
public:
	string m_name;
	int m_age;
public:
	Person(string name, int age)
	{
		this->m_name = name;
		this->m_age = age;
	}
	bool operator==(const Person& p)
	{
		if (this->m_age == p.m_age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
};

void test02()
{
	vector<Person>v;
	//创建并添加Person的数据
	Person p1("aaa", 10);Person p2("bbb", 20);
	Person p3("ccc", 30);Person p4("ddd", 20);
	v.push_back(p1);v.push_back(p2);
	v.push_back(p3);v.push_back(p4);
	
	Person p("bcd", 20);
	int num = count(v.begin(), v.end(), p); 
	cout << "和bcd相同年龄的人数为:" << num << endl;
}

6. cout_if

函数原型解释
cout_if(iterator begin, iterator end, _Pred);按条件统计元素出现次数

begin:开始迭代器
end:结束迭代器
_Pred:谓词(返回bool类型的仿函数)


三、排序算法

1. sort

对容器内元素进行排序(默认是从小到大)

函数原型解释
sort(iterator begin, iterator end, _Pred);按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

begin:开始迭代器
end:结束迭代器
_Pred:谓词(返回bool类型的仿函数)


2. random_shuffle

洗牌,指定范围内的元素随机调整次序

函数原型解释
random_shuffle(iterator begin, iterator end);指定范围内的元素随机调整次序

begin:开始迭代器
end:结束迭代器

建议使用时加随机数种子srand((unsigned int)time(NULL));


3. merge

容器元素合并,并存储到另一容器中

函数原型解释
merge(iterator begin1, iterator end1, iterator begin2, iterator end2, dest, _Pred(可省略,默认升序));容器元素合并,并存储到另一容器中

注意:两个容器必须是有序的

begin1:容器1的开始迭代器
end1:容器1的结束迭代器
begin2:容器2的开始迭代器
end2:容器2的结束迭代器
dest:目标容器的开始迭代器
_Pred:谓词(返回bool类型的仿函数),这里不一定需要写,除非自定义合并后的排序规则


4. reverse

反转指定范围的元素

函数原型解释
reverse(iterator begin, iterator end);反转指定范围内的元素(倒序)

begin:开始迭代器
end:结束迭代器


四、拷贝和替换算法

1. copy

容器内指定范围的元素拷贝到另一容器中

函数原型解释
copy(iterator begin, iterator end, dest);按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

begin:开始迭代器
end:结束迭代器
dest:目标容器的开始迭代器

注意:记得提前给目标容器开辟空间


2. replace

将容器内指定范围的旧元素修改为新元素

函数原型解释
replace(iterator begin, iterator end, old_value, new_value);将区间内的旧元素替换成新元素

begin:开始迭代器
end:结束迭代器
old_value:旧元素
new_value:新元素


3. replace_if

将容器内指定范围的满足条件的元素修改为新元素

函数原型解释
replace_if(iterator begin, iterator end, _pred, new_value);按条件替换元素,满足条件的替换为新元素

begin:开始迭代器
end:结束迭代器
_pred:谓词
new_value:新元素


4. swap

互换两个容器的元素

函数原型解释
swap(container c1, container c2);互换两个容器的元素

c1和c2:容器1和容器2

注意:swap交换容器时,注意交换的容器需要同种类型


五、算术生成算法

算数生成算法属于小型算法,使用时包含的头文件为#include< numeric >

1. accumulate

函数原型解释
accumulate(iterator begin, iterator end, value);计算容器元素累计总和

begin:开始迭代器
end:结束迭代器
value:起始值


2. fill

函数原型解释
fill(iterator begin, iterator end, value);向容器中添加元素

begin:开始迭代器
end:结束迭代器
value:填充的值


六、集合算法

1. set_intersection

求两个容器的交集

函数原型解释
set_intersection(iterator begin1, iterator end1, iterator begin2, iterator end2, iterator dest);求两个容器的交集

begin1:容器1的开始迭代器
end1:容器1的结束迭代器
begin2:容器2的开始迭代器
end2:容器2的结束迭代器
dest:目标容器的开始迭代器

注意:

  1. 两个集合必须是有序序列
  2. 目标容器开辟空间需要从两个容器中取小值
  3. set_intersection的返回值既是交集中最后一个元素的位置
class MyPrint {
public:
	void operator()(int val) {
		cout << val << " ";
	}
};

void test01() {
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10; i++) {
		v1.push_back(i);
		v2.push_back(i + 5);
	}
	vector<int>vTarget;
	//目标容器需要提前开辟空间
	//最特殊的情况,大容器包含小容器,需要从两个容器中取小值
	vTarget.resize(min(v1.size(), v2.size()));
	vector<int>::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
	
	for_each(vTarget.begin(), itEnd, MyPrint());
	//此处的结束迭代器用itEnd而不用vTarget.end(),因为不一定会出现最特殊的情况,那么空余的位置会被默认值0填充。
	cout << endl;
}

2. set_union

求两个容器的并集

函数原型解释
set_union(iterator begin1, iterator end1, iterator begin2, iterator end2, iterator dest);求两个容器的并集

begin1:容器1的开始迭代器
end1:容器1的结束迭代器
begin2:容器2的开始迭代器
end2:容器2的结束迭代器
dest:目标容器的开始迭代器

注意:

  1. 两个集合必须是有序序列
  2. 目标容器开辟空间需要两个容器相加
  3. set_union的返回值是并集中最后一个元素的位置
class MyPrint {
public:
	void operator()(int val) {
		cout << val << " ";
	}
};
void test01() {
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10; i++) {
		v1.push_back(i);
		v2.push_back(i + 5);
	}
	vector<int>vTarget;
	vTarget.resize(v1.size()+v2.size());
	vector<int>::iterator itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
	//返回目标容器的最后一个元素的迭代器地址
	
	for_each(vTarget.begin(), itEnd, MyPrint());
	cout << endl;
}

3. set_difference

求两个容器的差集

函数原型解释
set_difference(iterator begin1, iterator end1, iterator begin2, iterator end2, iterator dest);求两个容器的并集

begin1:容器1的开始迭代器
end1:容器1的结束迭代器
begin2:容器2的开始迭代器
end2:容器2的结束迭代器
dest:目标容器的开始迭代器

注意:

  1. 两个集合必须是有序序列
  2. 目标容器开辟空间需要从两个容器中取最大值
  3. set_difference的返回值是并集中最后一个元素的位置
class MyPrint {
public:
	void operator()(int val) {
		cout << val << " ";
	}
};

void test01() {
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
		v2.push_back(i + 5);
	}
	
	vector<int>vTarget;
	vTarget.resize(max(v1.size(),v2.size()));
	
	vector<int>::iterator itEnd1 = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
	cout << "v1和v2的差集为:" << endl;
	for_each(vTarget.begin(), itEnd1, MyPrint());
	cout << endl;
	
	cout << "v2和v1的差集为:" << endl;
	vector<int>::iterator itEnd2 = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), vTarget.begin());
	for_each(vTarget.begin(), itEnd2, MyPrint());
	cout << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值