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
常用算法篇幅也较长,所以就决定分几部分更新完,希望对大家有帮助,共勉!
笔记中有错误的地方,欢迎指出,欢迎大家讨论!