什么是泛型算法?通俗的说,就是这个写算法是不依赖数据类型的。比如查找某个元素,可以是对vector查找,也可以对list查找,甚至是对数组查找;这些算法的输入通常是一对迭代器来表明算法作用的范围。下面的例子显示了使用find函数和count函数。
//输入12个数
vector<int> ival;
for(int i = 0;i < 6;++i)
{
ival.push_back(i);
ival.push_back(i);
}
//find函数使用举例
cout<<"please enter the number to search: "<<endl;
int searchItem;
cin>>searchItem;
vector<int>::iterator iter = find(ival.begin(),ival.end(),searchItem);
//如果找到,则返回指向该元素的迭代器,否则返回第二个实参
if(iter != ival.end())
cout<<*iter<<"is in the vctor"<<endl;
else
cout<<"can't find the vaule!"<<endl;
//count函数使用举例
int times = count(ival.begin(),ival.end(),searchItem);
cout<<searchItem<<" occurs "<<times<<" times "<<endl;
算法不执行容器本身的操作,这意味着,我们不会使用ival.find来使用这个函数,虽然这个用法看上去更符合我的意愿,但我们一定不能忘记,算法库是泛型的,不依赖数据类型,所以算法不是执行在某种容器上的;更重要的一点是,这意味着普通的算法不会修改容器的大小。
算法库定义的算法很多,但是从大体上可以通过该算法如何操作元素来对其进行分类:是否读元素,是否写元素,是否重新排序元素。
对于只读算法,我们举一个简单的例子,对容器内的所有数字求和:accumulate
//accumulate函数使用举例:第三个参数是累加的初值
int sum = accumulate(ival.begin(),ival.end(),100);
cout<<"sum+100 = "<<sum<<endl;
需要注意的是,accumulate算法中,迭代器指明的类型必须与初值相匹配。
对于写算法,一定要注意写入的范围至少要在容器的范围之内:
比如fill函数:
//fill函数,最后一个元素没有被填入0
cout<<"enter the number you want to fill"<<endl;
int fillNumber;
cin>>fillNumber;
fill(ival.begin(),--ival.end(),fillNumber);
for(vector<int>::iterator it = ival.begin();it != ival.end();++it)
cout<<*it<<"\t";
cout<<endl;
fill_n函数:写入固定的数目:
//fill_n函数:前3个数填充为5
cout<<"first 3 number will be replaced by 5"<<endl;
fill_n(ival.begin(),3,5);
for(vector<int>::iterator it = ival.begin();it != ival.end();++it)
cout<<*it<<"\t";
cout<<endl;
为了防止越界,可以使用插入迭代器back_inserter,这样fill_n函数将会将添加的数字自动追加在ival的尾部。我们前面说过,算法并不直接修改容器的大小,但是这里使用的是迭代器修改的,所以并不矛盾。
//使用插入迭代器:20个元素都添加到尾部
cout<<"append 20 10s to the vctor: "<<endl;
fill_n(back_inserter(ival),20,10);
for(vector<int>::iterator it = ival.begin();it != ival.end();++it)
cout<<*it<<"\t";
cout<<endl;
对于排序算法,我们先看一个例子:
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
//定义谓词函数
bool isShorter(const string &s1,const string &s2)
{
return s1.size()<s2.size();
}
bool GT6(const string &s)
{
return s.size()>6;
}
int main()
{
cout<<"please enter some words"<<endl;
string word;
vector<string> words;
while(cin>>word)
words.push_back(word);
cout<<endl;
//sort算法对words中的元素排序
sort(words.begin(),words.end());
//输出结果
for(vector<string>::iterator iter = words.begin();iter != words.end();++iter)
cout<<*iter<<"\t";
//unique算法挑出容器中不重复的元素排在容器的前面,重复的排在后面,返回第一个重复的元素的位置
vector<string> ::iterator end_unique = unique(words.begin(),words.end());
//删除重复的单词
cout<<"without repeat words: "<<endl;
words.erase(end_unique,words.end());
for(vector<string>::iterator iter = words.begin();iter != words.end();++iter)
cout<<*iter<<"\t";
cout<<endl;
//使用带谓词函数的排序
cout<<"is shorter"<<endl;
stable_sort(words.begin(),words.end(),isShorter);
for(vector<string>::iterator iter = words.begin();iter != words.end();++iter)
cout<<*iter<<"\t";
cout<<endl;
vector<string>::size_type wc = 0;
//使用count_if
//wc = count_if(words.begin(),words.end(),GT6);
//使用find_if
vector<string>::iterator it = words.begin();
while((it = find_if(words.begin(),words.end(),GT6)) != words.end())
{
++it;
++wc;
}
cout<<wc<<" "<<"6 words or longer"<<endl;
return 0;
}
这个程序统计输入文字中大于6个字母的单词的个数。
其中sort按照字典的顺序排序,unique找出容器中不重复的单词,排在容器前面,重复的排在后面。返回指向第一个重复元素的迭代器,而stable_sort带谓词函数,是得我们能够定义自己的顺序,count_if检测使得谓词函数为真的容器元素的个数,同理还有find_if返回第一个使谓词函数非0的迭代器,这两种方法都可以完成统计大于6个字母的单词的目标。
算法库里面的东西很多,这里不可能对每种函数都做出实例解释,但是这些算法的命名和使用规则都很规范,以至于很多时候我们可以“望文生义”出某些算法的作用。
算法库的函数大都采用以下4中