1.前言
c++中的容器支持插入删除操作,支持获取第一个元素的迭代器和超过元素末端的下一迭代器操作......但是却不支持获取指定元素操作,比较操作,排序操作......因为这些操作都是和算法有关的,在C++中将它们独立出来,说明算法和具体的容器和具体的数据类型无关,只和自身的元素相关。比如find函数,用于查找指定的值,看下面两段代码:
vector<int> vect;
//往vect添加元素
vector<int>::iterator iter=find(vect.begin(),vect,end(),search_value);
list<int> lis;
//添加元素
list<int>::iterator iter=find(lis.begin(),lis.end(),search_value);
int a[5]={1,2,3,4,5};
int *result=find(a,a+5,search_value);
我们可以对于find函数来说,它对于容器的类型和数据类型都没有要求,即它只与自身的算法实现有关,和容器类型无关。除了迭代器之外,我们可以发现,指针也可以用于find函数的实参。所以对find函数来说只有几个要求:
①、数据类型必须是可以比较的,这样才可以判断是否是所查找的值。
②、必须给定一段范围,必须知道从哪里开始从哪里结束。
③、如果找到该值,就返回指向该值的指针或者迭代器,否则返回第二个参数即最后一个元素的下一个元素的地址。
在C++中提供了泛型算法,它包含在algorithm头文件中,以及一个泛化的算数算法,它包含在numeric头文件中。
2、只读算法
只读算法只会读取范围内的元素,而不对范围内的元素进行任何操作。前面的find函数就是一个例子,另一个就是accumulate函数,定义在numeric头文件中,它使用数据类型的加法操作进行将某段元素范围的元素相加。考虑下面的代码:
vecotr<int> vectInt;
vector<string> vectString;
int sum=accumulate(vectInt.begin(),vectInt.end(),0);
string result=accumulate(vectString.begin(),vectString.end(),string(""));
上述尝试对int和string元素进行相加操作,对于sum的值,它是以0为起始值,并把vectInt标记的元素范围内所有值的相加。对于accumulate来说,它并不知道要添加的元素的类型是什么,因此它是通过第三个参数来判断执行加操作符的意义的。比如result的结果则是,获取了一端拼接起来的字符串。注意这里不能替换为字符串字面值,因为字符串字面值是const char*类型,这样会导致编译错误。
在numeric头文件,还有很多find系列的函数,比如find_fisrt_of();此函数接受四个参数,分别标志两段数据范围,它的作用用于查找在这两段标志的区间里面重合的元素,如果找到了就返回第一段范围内第一个重合元素的迭代器,否则就返回第一段范围内最后一个元素的下一个元素的迭代器。看如下代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace::std;
int main()
{
vector<string> vect;
vect.push_back("harden");
vect.push_back("james");
vect.push_back("howard");
vect.push_back("harden");
vect.push_back("wade");
vector<string> vect1(vect);
vect1.erase(--vect1.end());
vector<string>::iterator it = vect.begin();
int count = 0;
while ((it = find_first_of(it, vect.end(), vect1.begin(), vect1.end())) != vect.end())
{
count++;
it++;
}
cout << count << endl;
system("pause");
return 0;
}
3、利用算法排序元素
C++提供了排序算法,可用于排序容器内的元素,比如sort,此方法有两个版本,一个是接受一对迭代器作为实参(此版本的方法默认是使用<比较符比较对象),另外一个是除了一对迭代器之外,还接受一个函数名称。对该函数是由要求的,比如如果排序的对象是vector<int>型,则该函数的返回值必须是bool,形参必须是两个int型对象的引用。
注意,任何算法都不会删除或修改添加容器元素的元素数据。因此C++还提供了一个unique算法,可以将所有容器中出现多次的内容都排到容器末端,并且返回指向第一个相同元素的迭代器。通过它,我们就可以避免重复对容器中相同的元素进行操作。
看下面的代码:
vector<string> vect;
vect.push_back("harden");
vect.push_back("james");
vect.push_back("howard");
vect.push_back("harden");
vect.push_back("wade");
/*
对容器内元素进行排序
*/
vect.push_back("james");
//sort 元素会对元素内的元素进行<排序
sort(vect.begin(), vect.end());
cout << "输出从小到大排序后的内容:";
for (vector<string>::iterator it = vect.begin(); it < vect.end(); ++it)
{
cout << *it<<" ";
}
cout << endl;
//此函数会将容器内的元素的相同元素都排到容器的末端,然后返回指向第一个相同元素的迭代器。即在此迭代器之前的元素都是唯一的
vector<string>::iterator uniqu_end = unique(vect.begin(), vect.end());
cout<<"输出不包含相同元素的容器内容:";
for (vector<string>::iterator it = vect.begin(); it < uniqu_end; ++it)
{
cout << *it << " ";
}
cout << endl;
//可使用erase将相同元素删掉。
vect.erase(uniqu_end, vect.end());
cout << "输出删除元素后的内容:";
for (vector<string>::iterator it = vect.begin(); it < vect.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
//使用sort的时候,也可以自带排序算法函数
sort(vect.begin(), vect.end(), isLonger);
cout << "输出从大到小排序元素后的内容:";
for (vector<string>::iterator it = vect.begin(); it < vect.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
isLonger函数如下:
bool isLonger(string &one, string &two)
{
return one > two;
}
输出结果:
4.迭代器综述
我们一般接触的迭代器都是正向迭代器,其实C++还提供了正向迭代器,iostream迭代器,插入迭代器。如下:
有关算法是不和容器捆绑的,除了前面提到的算法之外,还有很多不常用的算法,希望读者有兴趣的多去了解。