(转)常用算法(Algorithm)的用法介绍
²算法部分主要由头文件<algorithm>,<numeric>和<functional>组成。
²<algorithm>是所有STL头文件中最大的一个,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、反转、排序、合并等等。
²<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。
²<functional>中则定义了一些模板类,用以声明函数对象。
²STL提供了大量实现算法的模版函数,只要我们熟悉了STL之后,许多代码可以被大大的化简,只需要通过调用一两个算法模板,就可以完成所需要的功能,从而大大地提升效率
#include <algorithm>
#include <numeric>
#include <functional>
using namespace std;
²常用的查找算法:
adjacent_find()( adjacent 是邻近的意思),binary_search(),count(),
count_if(),equal_range(),find(),find_if()。
²常用的排序算法:
merge(),sort(),random_shuffle()(shuffle是洗牌的意思) ,reverse()。
²常用的拷贝和替换算法:
copy(), replace(),
replace_if(),swap()
²常用的算术和生成算法:
accumulate()( accumulate 是求和的意思),fill(),。
²常用的集合算法:
set_union(),set_intersection(),
set_difference()。
²常用的遍历算法:
for_each(), transform()( transform 是变换的意思)
²adjacent_find(): 在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的迭代器。否则返回past-the-end。
例如:vecInt是用vector<int>声明的容器,现已包含1,2,2,4,5元素。
vector<int>::iteratorit=adjacent_find(vecInt.begin(),vecInt.end());
此时 *it == 2
²binary_search: 在有序序列中查找value,找到则返回true。注意:在无序序列中,不可使用。
例如: setInt是用set<int>声明的容器,现已包含1,3,5,7,9元素。
bool bFind =binary_search(setInt.begin(),setInt.end(),5);
此时 bFind == true
²count: 利用等于操作符,把标志范围内的元素与输入值比较,返回相等的个数。
²count_if: 利用输入的函数,对标志范围内的元素进行比较操作,返回结果为true的个数。
例如:vecInt是用vector<int>声明的容器,已包含1,3,5,7,9元素,现要求求出大于等于3的元素个数
//先定义比较函数
bool GreaterThree(int iNum)
{
if(iNum>=3)
{
return true;
}
else
{
return false;
}
}
int iCount = count_if(vecIntA.begin(),vecIntA.end(), GreaterThree);
//此时iCount == 4
²equal_range: 返回一对iterator,第一个表示lower_bound,第二个表示upper_bound。
²
²find: 利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较。当匹配时,结束搜索,返回该元素的迭代器。
例如: vecInt是用vector<int>声明的容器,已包含1,3,5,7,9
vector<int>::iterator it =find(vecInt.begin(),vecInt.end(),5);
此时 *it == 5
²find_if: 使用输入的函数代替等于操作符执行find。返回被找到的元素的迭代器。
例如:vecInt是用vector<int>声明的容器,已包含1,3,5,3,9元素。现要找出第一个大于等于3的元素的迭代器。
vector<int>::iterator it =find_if(vecInt.begin(),vecInt.end(),GreaterThree);
此时 *it==3, *(it+1)==5,*(it+2)==3, *(it+3)==9
²常用的查找算法:
adjacent_find(),binary_search(),count(),
count_if(),equal_range(),find(),find_if()。
²常用的排序算法:
merge(),sort(),random_shuffle(),reverse()。
²常用的拷贝和替换算法:
copy(), replace(),
replace_if(),swap()
²常用的算术和生成算法:
accumulate(),fill()
²常用的集合算法:
set_union(),set_intersection(),
set_difference()。
²常用的遍历算法:
for_each(), transform()
²以下是排序和通用算法:提供元素排序策略
²merge: 合并两个有序序列,存放到另一个序列。
例如:vecIntA,vecIntB,vecIntC是用vector<int>声明的容器,vecIntA已包含1,3,5,7,9元素,vecIntB已包含2,4,6,8元素
vecIntC.resize(9); //扩大容量
merge(vecIntA.begin(),vecIntA.end(),vecIntB.begin(),vecIntB.end(),vecIntC.begin());
此时vecIntC就存放了按顺序的1,2,3,4,5,6,7,8,9九个元素
²sort: 以默认升序的方式重新排列指定范围内的元素。若要改排序规则,可以输入比较函数。
例如: vecInt是用vector<int>声明的容器,已包含2,1,4,3,6,5元素
sort(vecInt.begin(),vecInt.end());
此时,vecInt包含了1,2,3,4,5,6元素。
如果vector<T>,T是自定义类型,则要提供T类型的比较函数
学生类有学号跟姓名的属性,有一个存着学生对象的vector容器,要使该容器按学号升序排序。
//学生类
Class CStudent:
{
public:
CStudent(int iID, string strName)
{m_iID=iID; m_strName=strName; }
public:
int m_iID;
string m_strName;
}
²//学号比较函数
bool Compare(const CStudent &stuA,constCStudent &stuB)
{
return(stuA.m_iID<strB.m_iID);
}
void main()
{
vector<CStudent> vecStu;
vecStu.push_back(CStudent(2,"老二"));
vecStu.push_back(CStudent(1,"老大"));
vecStu.push_back(CStudent(3,"老三"));
vecStu.push_back(CStudent(4,"老四"));
sort(vecStu.begin(),vecStu.end(),Compare);
// 此时,vecStu容器包含了按顺序的"老大对象","老二对象","老三对象","老四对象"
}
²random_shuffle: 对指定范围内的元素随机调整次序。
²reverse: 对指定范围内元素重新反序排序
²常用的查找算法:
adjacent_find(),binary_search(),count(),
count_if(),equal_range(),find(),find_if()。
²常用的排序算法:
merge(),sort(),random_shuffle(),reverse()。
²常用的拷贝和替换算法:
copy(), replace(),
replace_if(),swap()
²常用的算术和生成算法:
accumulate(),fill(),。
²常用的集合算法:
set_union(),set_intersection(),
set_difference()。
²常用的遍历算法:
for_each(), transform()
copy: 复制序列
例如:vecIntA,vecIntB是用vector<int>声明的对象,vecIntA已包含1,3,5,7,9元素。
vecIntB.resize(5);
copy(vecIntA.begin(),vecIntA.end(),vecIntB.begin());
此时vecIntB也包含了1,3,5,7,9元素
²replace_if : 将指定范围内所有操作结果为true的元素用新值替换。
用法举例:
replace_if(vecIntA.begin(),vecIntA.end(),GreaterThree,newVal)
其中 vecIntA是用vector<int>声明的容器
GreaterThree 函数的原型是 bool GreaterThree(int iNum)
swap: 交换两个容器的元素
²accumulate: 对指定范围内的元素求和,然后结果再加上一个由val指定的初始值。
²fill: 将输入值赋给标志范围内的所有元素。
讲解要点
一、容器的共通能力;
二、各个容器的使用时机;
三、常用算法(Algorithm)的用法介绍。
各个容器的使用时机
adjacent_find()
vector<int>vecInt;
vecInt.push_back(1);
vecInt.push_back(2);
vecInt.push_back(2);
vecInt.push_back(4);
vecInt.push_back(5);
vector<int>::iteratorit = adjacent_find(vecInt.begin(),vecInt.end()); //*it == 2
binary_search
set<int>setInt;
setInt.insert(3);
setInt.insert(1);
setInt.insert(7);
setInt.insert(5);
setInt.insert(9);
boolbFind = binary_search(setInt.begin(),setInt.end(),5);
count()
vector<int> vecInt;
vecInt.push_back(1);
vecInt.push_back(2);
vecInt.push_back(2);
vecInt.push_back(4);
vecInt.push_back(2);
vecInt.push_back(5);
intiCount =count(vecInt.begin(),vecInt.end(),2); //iCount==3
count_if()
假设vector<int>vecIntA,vecIntA包含1,3,5,7,9元素
//先定义比较函数
bool GreaterThree(int iNum)
{
if(iNum>=3)
{
returntrue;
}
else
{
returnfalse;
}
}
int iCount =count_if(vecIntA.begin(),vecIntA.end(), GreaterThree);
//此时iCount == 4
find()
vector<int> vecInt;
vecInt.push_back(1);
vecInt.push_back(3);
vecInt.push_back(5);
vecInt.push_back(7);
vecInt.push_back(9);
vector<int>::iterator it =find(vecInt.begin(),vecInt.end(),5); //*it ==5
find_if()
假设vector<int>vecIntA,vecIntA包含1,3,5,3,9元素
vector<int>::it=find_if(vecInt.begin(),vecInt.end(),GreaterThree);
此时 *it==3,*(it+1)==5,*(it+2)==3, *(it+3)==9
merge()
例如:vecIntA,vecIntB,vecIntC是用vector<int>声明的容器,vecIntA已包含1,3,5,7,9元素,vecIntB已包含2,4,6,8元素
vecIntC.resize(9); //扩大容量
merge(vecIntA.begin(),vecIntA.end(),vecIntB.begin(),vecIntB.end(),vecIntC.begin());
此时vecIntC就存放了按顺序的1,2,3,4,5,6,7,8,9九个元素
sort()
//学生类
Class CStudent:
{
public:
CStudent(intiID, string strName)
{
m_iID=iID;
m_strName=strName;
}
public:
intm_iID;
stringm_strName;
}
//学号比较函数
bool Compare(const CStudent&stuA,constCStudent &stuB)
{
return (stuA.m_iID<strB.m_iID);
}
void main()
{
vector<CStudent>vecStu;
vecStu.push_back(CStudent(2,"老二"));
vecStu.push_back(CStudent(1,"老大"));
vecStu.push_back(CStudent(3,"老三"));
vecStu.push_back(CStudent(4,"老四"));
sort(vecStu.begin(),vecStu.end(),Compare);
// 此时,vecStu容器包含了按顺序的"老大对象","老二对象","老三对象","老四对象"
}
random_shuffle()
srand(time(0)); //设置随机种子
vector<int>vecInt;
vecInt.push_back(1);
vecInt.push_back(3);
vecInt.push_back(5);
vecInt.push_back(7);
vecInt.push_back(9);
stringstr("UIPower");
random_shuffle(vecInt.begin(),vecInt.end()); //随机排序,结果比如:9,7,1,5,3
random_shuffle(str.begin(),str.end()); //随机排序,结果比如:"owreUIP"
reverse()
vector<int>vecInt;
vecInt.push_back(1);
vecInt.push_back(3);
vecInt.push_back(5);
vecInt.push_back(7);
vecInt.push_back(9);
reverse(vecInt.begin(),vecInt.end()); //{9,7,5,3,1}
copy()
vector<int> vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vecIntA.push_back(7);
vecIntA.push_back(9);
vector<int>vecIntB;
vecIntB.resize(5); //扩大空间
copy(vecIntA.begin(),vecIntA.end(), vecIntB.begin()); //vecIntB:{1,3,5,7,9}
replace()
vector<int>vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vecIntA.push_back(3);
vecIntA.push_back(9);
replace(vecIntA.begin(),vecIntA.end(), 3,8); //{1,8,5,8,9}
replace_if()
//把大于等于3的元素替换成8
vector<int>vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vecIntA.push_back(3);
vecIntA.push_back(9);
replace_if(vecIntA.begin(),vecIntA.end(), GreaterThree,8); //GreaterThree的定义在上面。
swap()
vector<int>vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vector<int>vecIntB;
vecIntB.push_back(2);
vecIntB.push_back(4);
swap(vecIntA,vecIntB); //交换
accumulate()
vector<int>vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vecIntA.push_back(7);
vecIntA.push_back(9);
intiSum = accumulate(vecIntA.begin(), vecIntA.end(),100); //iSum==125
fill()
vector<int>vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vecIntA.push_back(7);
vecIntA.push_back(9);
fill(vecIntA.begin(),vecIntA.end(),8); //8, 8, 8,8, 8
set_union(),set_intersection(),set_difference()
vector<int> vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vecIntA.push_back(7);
vecIntA.push_back(9);
vector<int>vecIntB;
vecIntB.push_back(1);
vecIntB.push_back(3);
vecIntB.push_back(5);
vecIntB.push_back(6);
vecIntB.push_back(8);
vector<int>vecIntC;
vecIntC.resize(10);
//交集
set_union(vecIntA.begin(),vecIntA.end(), vecIntB.begin(), vecIntB.end(),vecIntC.begin()); //vecIntC :{1,3,5,6,7,8,9,0,0,0}
//并集
fill(vecIntC.begin(),vecIntC.end(),0);
set_intersection(vecIntA.begin(),vecIntA.end(), vecIntB.begin(), vecIntB.end(),vecIntC.begin()); //vecIntC:{1,3,5,0,0,0,0,0,0,0}
//差集
fill(vecIntC.begin(),vecIntC.end(),0);
set_difference(vecIntA.begin(),vecIntA.end(), vecIntB.begin(), vecIntB.end(),vecIntC.begin()); //vecIntC:{7,9,0,0,0,0,0,0,0,0}
for_each()
void show(const int &iItem)
{
cout<< iItem;
}
main()
{
intiArray[] = {0,1,2,3,4};
vector<int>vecInt(iArray,iArray+sizeof(iArray)/sizeof(iArray[0]));
for_each(vecInt.begin(),vecInt.end(), show);
//结果打印出0 1 2 3 4
}
transform()
int increase (int i)
{
returni+1;
}
main()
{
vector<int>vecIntA;
vecIntA.push_back(1);
vecIntA.push_back(3);
vecIntA.push_back(5);
vecIntA.push_back(7);
vecIntA.push_back(9);
transform(vecIntA.begin(),vecIntA.end(),vecIntA.begin(),increase); //vecIntA : {2,4,6,8,10}
}