STL中的常用算法(一)

12 篇文章 0 订阅
9 篇文章 0 订阅

STL中的常用算法:

写在前面的话:

	好长时间没有写博客了,大致有半年的时间,之前因为忙一些其他的事,所以博客就处于停更的状态。
	时隔半年,我又想重新拿起笔,重拾起写博客的兴趣,就以这篇博客为起点重新开始吧!

之前已经基本介绍了一些 C++ STL 中的常用容器,接下来就是 C++ STL 中的常用算法了;


STL常用算法:

概述

1.使用 STL 中的常用算法往往需要包含以下头文件: #include <algorithm>#include <functional>#include <numeric>

2.<algorithm> 是所有 STL 头文件中最大的一个,范围涉及比较交换查找遍历复制修改等等;

3.<numeric> 体积很小,只包含几个在序列上面进行简单数学运算的模板函数;

4.<functional> 定义了一些模板类,用以声明函数对象;


常用遍历算法

1.for_each 算法:用于遍历容器;

函数原型:for_each(iterator begin,iterator end,_func);

begin起始迭代器end结束迭代器_func普通函数或者仿函数

#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;

void printVector_1(int value)  //普通函数
{
	cout << value << " ";
}

class printVector_2  //仿函数
{
public:
	void operator()(int value)
	{
		cout << value << " ";
	}
};

void test_1()  //常用遍历算法 for_each() 
{
	int i = 0;
	vector<int> v1;
	
	for(i=0;i<10;i++)
	{
		v1.push_back(i+1);
	}
	
	//常用遍历算法 for_each(),前两个参数分别为起始迭代器和结束迭代器,最后一个参数是函数或者仿函数
	
	for_each(v1.begin(),v1.end(),printVector_1);  //普通函数,这里利用了函数回调的技术 
	cout << endl;
	
	for_each(v1.begin(),v1.end(),printVector_2());  //仿函数,这里利用了函数回调的技术
	cout << endl;
}

int main()
{
	test_1();
	
	system("pause");
	return 0;
}

2.transform 算法:用于两个容器之间的搬运

函数原型:transform(iterator begin_1,iterator end_1,iterator begin_2,_func);

begin_1源容器的起始迭代器,end_1源容器的结束迭代器,begin_2目标容器的起始迭代器,_func函数仿函数

#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;

class Transform
{
public:
	int operator()(int value)
	{
		return value;
	}	
};

class printVector
{
public:
	void operator()(int value)
	{
		cout << value << " ";
	}	
};

void test_1()  //常用遍历算法 搬运算法 transfrom() 
{
	int i = 0;
	vector<int> v1;  //源容器v1 
	
	for(i=0;i<10;i++)
	{
		v1.push_back(i+1);
	}
	
	vector<int> v2;  //目标容器v2
	
	//在用到搬运算法transfrom()前,得先保证目标容器有足够的空间,因此要先给目标容器开辟足够的空间
	v2.resize(v1.size());
	
	//搬运算法 transform(),前两个参数分别为源容器的起始迭代器和结束迭代器,第三个参数为目标容器的起始迭代器,第四个参数为普通函数或仿函数 
	transform(v1.begin(),v1.end(),v2.begin(),Transform());
	
	//遍历输出打印容器v2 
	for_each(v2.begin(),v2.end(),printVector());
	cout << endl;
}

int main()
{
	test_1();
	
	system("pause");
	return 0;
}

常用查找算法

1.find() 算法:查找指定元素是否存在;

函数原型:find(iterator begin,iterator end,value);

begin起始迭代器end结束迭代器value 是要查找的目标元素;若目标元素在容器中存在,该算法会返回目标元素的迭代器

若目标元素在容器中,不存在,则会返回 end(),因此该算法的返回值要用迭代器接收;

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
 
using namespace std;

//常用查找算法 find()
 
void test_1()  //查找内置数据类型是否存在
{
	int i = 0;
	vector<int> v1;
	
	for(i=0;i<10;i++)
	{
		v1.push_back(i+1);
	}
	
	//查找元素5是否存在于容器中 
	vector<int>::iterator pos = find(v1.begin(),v1.end(),5);
	
	if(pos==v1.end())
	{
		cout << "目标元素不存在" << endl;
	}
	else
	{
		cout << "目标元素存在,该元素为:" << *pos << endl;
	}
}

class Person  //人类 
{
public:
	Person(string name,int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	
	//重载==运算符,使得底层find()函数知道如何去对比两个对象 
	bool operator==(const Person & p)
	{
		if(this->m_Name==p.m_Name&&this->m_Age==p.m_Age)
		{
			return true;
		}
		else
		{
			return false;
		} 
	}

	string m_Name;  //姓名
	int m_Age;  //年龄 
};

void test_2()  //查找自定义数据类型是否存在
{
	vector<Person> v1;
	
	//创建四个对象 
	Person p1("aaa",10);
	Person p2("bbb",20);
	Person p3("ccc",30);
	Person p4("ddd",40);
	
	//把创建好的对象插入到容器中
	v1.push_back(p1);
	v1.push_back(p2);
	v1.push_back(p3);
	v1.push_back(p4);
	
	//创建要查找的目标对象(与对象p2完全一致) 
	Person p_Target("bbb",20);
	
	vector<Person>::iterator pos = find(v1.begin(),v1.end(),p_Target);  //底层find()函数并不知道自定义数据类型如何对比,因此需要重载==运算符
	
	if(pos==v1.end())
	{
		cout << "没有找到目标对象" << endl;
	}
	else
	{
		cout << "目标对象存在,其姓名为:" << pos->m_Name << ",年龄为:" << (*pos).m_Age << endl; 
	}
}

int main()
{
	test_1();
	test_2();
	
	system("pause");
	return 0;
}

2.find_if() 算法:根据条件查找对应元素;

函数原型:find_if(iterator begin,iterator end,_Pred);

begin起始迭代器end结束迭代器_Pred谓词(返回类型为 bool 类型的仿函数),返回值用迭代器接收;

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
 
using namespace std;

//常用查找算法 find_if()

class GreaterFive
{
public:
	bool operator()(int value)
	{
		if(value>5)
		{
			return true;
		}
		else
		{
			return false;
		}
	}	
};

void test_1()  //查找内置数据类型是否存在
{
	int i = 0;
	int sign = 0;  //标志变量,起到标记的作用 
	vector<int> v1;
	
	for(i=0;i<10;i++)
	{
		v1.push_back(i+1);
	}
	
	//查找大于5的元素 
	vector<int>::iterator pos = find_if(v1.begin(),v1.end(),GreaterFive());
	
	while(pos!=v1.end())
	{
		cout << "找到大于5的元素:" << *pos << endl;
		pos++;
		sign = 1;
	}
	
	if(sign==0)
	{
		cout << "没有找到大于5的元素" << endl;
	}
}

class Person  //人类 
{
public:
	Person(string name,int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	
	string m_Name;  //姓名
	int m_Age;  //年龄	
};

class AgeGreaterTwenty
{
public:
	
	bool operator()(Person & p)
	{
		if(p.m_Age>20)
		{
			return true;
		}
		else
		{
			return false;
		}
	}	
};

void test_2()  //查找自定义数据类型是否存在
{
	int sign = 0;  //标志变量,起到标记的作用 
	vector<Person> v1;
	
	//创建五个对象
	Person p1("aaa",10);
	Person p2("bbb",20);
	Person p3("ccc",30);
	Person p4("ddd",40);
	Person p5("eee",50);
	
	//将创建好的对象插入到容器中
	v1.push_back(p1);
	v1.push_back(p2);
	v1.push_back(p3);
	v1.push_back(p4);
	v1.push_back(p5);
	
	//查找年龄大于20岁的人 
	vector<Person>::iterator pos = find_if(v1.begin(),v1.end(),AgeGreaterTwenty());
	
	while(pos!=v1.end())
	{
		cout << "找到年龄大于20岁的人,姓名为:" << (*pos).m_Name << ",年龄为:" << pos->m_Age << endl;
		pos++;
		sign = 1;
	}
	
	if(sign==0)
	{
		cout << "没有找到20岁以上的人" << endl;
	}
}

int main()
{
	test_1();
	test_2();
	
	system("pause");
	return 0;
}

3.adjacent_find() 算法:查找相邻重复的元素;

函数原型:adjacent_find(iterator begin,iterator end);

begin起始迭代器end结束迭代器,其返回相邻重复元素的第一个位置的迭代器,返回值要用迭代器接收;

#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;

void test_1()  //常用查找算法 adjacent_find()
{
	vector<int> v1;
	
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(2);
	v1.push_back(4);
	v1.push_back(1);
	v1.push_back(3);  //迭代器返回的位置 
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(4);
	
	vector<int>::iterator pos = adjacent_find(v1.begin(),v1.end());
	
	if(pos==v1.end())
	{
		cout << "没有找到相邻重复元素" << endl;
	}
	else
	{
		cout << "找到相邻重复元素:" << *pos << endl;
	}
} 

int main()
{
	test_1();
	
	system("pause");
	return 0;
}

4.binary_search() (二分查找)算法:查找指定的元素;若查找成功,则返回 true,若查找失败,则返回 false

注意:该查找算法虽然查找效率很高,但只适用于有序序列(且排序规则必须为从小到大),在无序序列降序序列中不可使用;

函数原型:bool binary_search(iterator begin,iterator end,value);

begin起始迭代器end结束迭代器value 是要查找的目标元素

#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;

class MySort  //修改排序规则为:从大到小 
{
public:
	bool operator()(int value_1,int value_2)
	{
		if(value_1>value_2)
		{
			return true;
		}
		else
		{
			return false;
		}
	}	
};

void test_1()  //常用查找算法 binary_search()
{
	vector<int> v1;
	
    //向容器v1中无序插入数据
	v1.push_back(20);
	v1.push_back(10);
	v1.push_back(40);
	v1.push_back(50);
	v1.push_back(30);
	
	//首先对容器内的数据进行排序,因为该查找算法只适用于有序序列(且排序规则为:从小到大),在无序序列或降序序列中使用会出错 
	sort(v1.begin(),v1.end());
	
    //查找元素40是否存在
	bool ret = binary_search(v1.begin(),v1.end(),40);
	
	if(ret)
	{
		cout << "找到目标元素" << endl; 
	}
	else
	{
		cout << "未找到目标元素" << endl;
	}
}

//经检验,该查找算法是无法查找自定义数据类型的,只能查找内置的数据类型
//查看底层后发现,可能需要重载<才可以实现二分查找法查找自定义数据类型,具体还要深入了解二分查找的机制

int main()
{
	test_1();
	
	system("pause");
	return 0;
}

5.count() 算法:统计目标元素的个数;

函数原型:count(iterator begin,iterator end,value);

begin起始迭代器end结束迭代器value 是要查找的目标元素,该算法的返回值为目标元素的个数

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
 
using namespace std;

//常用查找算法 count() 

void test_1()  //统计内置数据类型 
{
	vector<int> v1;
	
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(2);
	v1.push_back(5);
	v1.push_back(1);
	v1.push_back(4);
	v1.push_back(3);
	v1.push_back(1);
	
	//统计1的个数 
	int num = count(v1.begin(),v1.end(),1);
	
	cout << "1的个数为:" << num << endl;
}

class Person  //人类 
{
public:
	Person(string name,int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	
	//重载==运算符,使得底层count()函数知道如何去判断两个对象年龄是否相等 
	bool operator==(const Person & p)
	{
		if(this->m_Age==p.m_Age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	string m_Name;  //姓名
	int m_Age;  //年龄	
};

void test_2()  //统计自定义数据类型 
{
	vector<Person> v1;
	
	//创建六个对象
	Person p1("刘备",30);
	Person p2("关羽",35);
	Person p3("张飞",30);
	Person p4("曹操",45);
	Person p5("赵云",25);
	Person p6("马超",30);
	
	//把创建好的对象插入到容器中
	v1.push_back(p1);
	v1.push_back(p2);
	v1.push_back(p3);
	v1.push_back(p4);
	v1.push_back(p5);
	v1.push_back(p6);
	
	//统计与诸葛亮同岁的人 
	Person p("诸葛亮",30);
	
	int num = count(v1.begin(),v1.end(),p);
	
	cout << "与诸葛亮同岁的人的人数为:" << num << endl; 
}

int main()
{
	test_1();
	test_2();
	
	system("pause");
	return 0;
}

6.count_if() 算法:根据条件统计目标元素的个数;

函数原型:count_if(iterator begin,iterator end,_Pred);

begin起始迭代器end结束迭代器_Pred谓词,该算法的返回值为目标元素的个数

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
 
using namespace std;

//常用查找算法 count()_if

class GreaterTwo
{
public:
	bool operator()(int value)
	{
		if(value>2)
		{
			return true;
		}
		else
		{
			return false;
		}
	}	
};

void test_1()  //统计内置数据类型 
{
	vector<int> v1;
	
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(2);
	v1.push_back(5);
	v1.push_back(1);
	v1.push_back(4);
	v1.push_back(3);
	v1.push_back(1);
	
	//统计大于2的元素的个数 
	int num = count_if(v1.begin(),v1.end(),GreaterTwo());
	
	cout << "大于2的元素的个数为:" << num << endl;
}

class Person  //人类 
{
public:
	Person(string name,int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	
	string m_Name;  //姓名
	int m_Age;  //年龄	
};

class AgeGreaterThirty
{
public:
	bool operator()(const Person & p)
	{
		if(p.m_Age>30)
		{
			return true;
		}
		else
		{
			return false;
		}
	}	
};

void test_2()  //统计自定义数据类型 
{
	vector<Person> v1;
	
	//创建七个对象
	Person p1("刘备",30);
	Person p2("关羽",35);
	Person p3("张飞",30);
	Person p4("曹操",45);
	Person p5("赵云",25);
	Person p6("马超",30);
	Person p7("孙权",36);
	
	//把创建好的对象插入到容器中
	v1.push_back(p1);
	v1.push_back(p2);
	v1.push_back(p3);
	v1.push_back(p4);
	v1.push_back(p5);
	v1.push_back(p6);
	v1.push_back(p7); 
	
	//统计年龄大于30的人的数量
	int num = count_if(v1.begin(),v1.end(),AgeGreaterThirty());
	
	cout << "年龄大于30的人的数量为:" << num << endl; 
}

int main()
{
	test_1();
	test_2();
	
	system("pause");
	return 0;
}

常用排序算法

1.sort() 算法:对容器内的元素进行排序(默认排序规则:从小到大排,即升序),该算法也是最常用的一种排序算法;

函数原型:sort(iterator begin,iterator end,_Pred);

begin起始迭代器end结束迭代器_Pred谓词,如果谓词的位置不填任何东西,该算法就会以默认排序规则进行排序;

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
 
using namespace std;

void myPrint(int value)
{
	cout << value << " ";
}

void test_1()  //常用排序算法 sort() 
{
	vector<int> v1;
	
    //向容器v1中无序插入数据
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(10);
	v1.push_back(50);
	v1.push_back(40);
	
	//从小到大进行排序(即升序)
	sort(v1.begin(),v1.end());
	for_each(v1.begin(),v1.end(),myPrint);
	cout << endl;
	
	//从小到大进行排序(即降序)
	sort(v1.begin(),v1.end(),greater<int>());
	for_each(v1.begin(),v1.end(),myPrint);
	cout << endl;
}

int main()
{
	test_1();
	
	system("pause");
	return 0;
}

2.random_shuffle() 算法:可以将指定范围内的元素随机调整次序,因此它也被称为洗牌算法

函数原型:random_shuffle(iterator begin,iterator end);

begin起始迭代器end结束迭代器,然后 random_shuffle() 算法可以将这个范围内的进行随机打乱

#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
 
using namespace std;

class MyPrint
{
public:
	void operator()(int value)
	{
		cout << value << " ";
	}	
};

void test_1()  //常用排序算法 random_shuffle() 
{
	int i = 0;
	vector<int> v1;
	
    //向容器v1中按顺序插入元素:1 2 3 4 5 6 7 8 9 10
	for(i=0;i<10;i++)
	{
		v1.push_back(i+1);
	}
	
	//将v1.begin()和v1.end()之间的元素随机打乱 
	random_shuffle(v1.begin(),v1.end());
	
	for_each(v1.begin(),v1.end(),MyPrint());
	cout << endl;
}

int main()
{
	//初始化随机数种子 
	srand((unsigned int)time(NULL));
	
	test_1();
	
	system("pause");
	return 0;
}

3.merge() 算法:将两个容器合并,并存储到另一个容器中;


函数原型:merge(iterator begin_1,iterator end_1,iterator begin_2,iterator end_2,iterator dest);

begin_1 是源容器 1起始迭代器end_1 是源容器 1结束迭代器begin_2 是源容器 2起始迭代器end_2 是源容器 2

结束迭代器dest 是目标容器的起始迭代器


注意

1.要合并的两个容器必须有序,且排序规则一致;它们合并和储存到目标容器的过程中,目标容器会自动的对元素做排序操作;

2.目标容器自动排序的操作,只有原来两个容器的排序都**符合默认排序规则(从小到大)**才可以实现;其他情况,只合并不排序;

3.目标容器需要提前分配好内存空间,否则是无法将合并后的容器存储到目标容器中的;


#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;

void myPrint(int value)
{
	cout << value << " ";
}

void test_1()  //常用排序算法 merge() 
{
	int i = 0;
	vector<int> v1;  //源容器一 
	vector<int> v2;  //源容器二
	
	for(i=0;i<10;i++)  //插入时按升序插入 
	{
		v1.push_back(i+1);  //1 2 3 4 5 6 7 8 9 10
		v2.push_back(i+2);  //2 3 4 5 6 7 8 9 10 11
	}
	
	vector<int> v_Target;  //目标容器
	
	//目标容器提前分配好内存空间
	v_Target.resize(v1.size()+v2.size());
	
	merge(v1.begin(),v1.end(),v2.begin(),v2.end(),v_Target.begin());
	
    //输出:1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11
	for_each(v_Target.begin(),v_Target.end(),myPrint);
	cout << endl;
}

int main()
{
	test_1();
	
	system("pause");
	return 0;
}

4.reverse() 算法:将容器内的元素进行反转

函数原型:reverse(iterator begin,iterator end);

begin起始迭代器end结束迭代器,然后 reverse() 算法可以将这个范围内的元素进行反转操作;

#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;

class MyPrint
{
public:
	void operator()(int value)
	{
		cout << value << " ";
	}	
};

void test_1()  //常用排序算法 reverse() 
{
	int i = 0;
	vector<int> v1;
	
	for(i=0;i<10;i++)
	{
		v1.push_back(i+1);
	}
	
	cout << "容器反转前:" << endl;
	for_each(v1.begin(),v1.end(),MyPrint());
	cout << endl;
	
	//将容器内的元素进行反转 
	reverse(v1.begin(),v1.end());
	
	cout << "容器反转后:" << endl;
	for_each(v1.begin(),v1.end(),MyPrint());
	cout << endl;
}

int main()
{
	test_1();
	
	system("pause");
	return 0;
}

这里就先暂时介绍一部分,STL 常用算法篇幅也较长,所以就决定分几部分更新完,希望对大家有帮助,共勉!

笔记中有错误的地方,欢迎指出,欢迎大家讨论!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值