1、简介

标准库容器定义的操作非常少,标准库没有给容器添加大量的功能函数,而是选择提供一组算法,这些算法大都不依赖特定的容器类型,是“泛型”的,可作用在不同类型的容器不同类型的元素上。

标准容器定义了很少的操作:添加和删除元素,访问第一个和最后一个元素,获取容器的大小,并在某种情况下重设容器的大小,以及获取指向第一个元素和最后一个元素的下一位置的迭代器。

用户还希望对容器元素进行更多的其他有用的操作,如:给顺序容器中的元素排序或者查找某个特定的元素,或者查找最大或最小的元素等等。标准库并没有为每种容器类型都定义实现这些操作的成员函数(有的定义了),而是定义了一组“泛型算法”:因为他们实现共同的操作,所以称之为“算法”,而“泛型”指的是他们可以操作在多种容器类型上---不但可以在vectorlist等标准库类型,也可用在内置数组类型上等。

大多数算法是通过遍历两个迭代器标记的一段元素来实现功能。

2、常用泛型算法

1find算法(只读算法

使用两个迭代器和一个值调用find函数,检查两个迭代器实参标记范围内的每一个元素,只要找到与给定的值相等,find就会返回指向该元素的迭代器,如果没有匹配的元素,find返回它的第二个迭代器实参,表示查找失败。于是,只要检查函数的返回值是否与它的第二个实参相等,就可得知元素是否找到了。

举个简单的例子:

int search_value = 42;

vector<int>::const_iterator result = find(vec.begin(),vec.end(),search_value);

if(result == vec.end())

cout<<"not present"<<endl;

else

cout<<"present"<<endl;

(2)accumulate算法(只读算法

前两个形参指定要累加的元素范围,第三个形参是累加的初值,算法返回累加的结果,返回类型是第三个实参的类型

举个简单的例子:

int sum = accumulate(vec.begin(),vec.end(),42);

string sum = accumulate(v.begin(),v.end(),string(""));

(3)fill算法(写算法

将值写入到目标迭代器指定的范围内。前两个表示填充的范围

举个简单的例子:

fill(vec.begin(),vec.end(),0);

vec容器中的所有元素重新赋值为0

(4)fill_n算法(写算法

fill_n(vec.begin(),10,0)

vec容器开始处的10个元素赋值为0,假如容器为空或当前容器的元素个数少于10个,会出错。

back_inserter():插入迭代器。使用一个容器对象作为实参。back_inserter生成一个绑定在该容器上的插入迭代器,在试图通过这个迭代器给元素赋值时,赋值运算将调用push_back在容器中添加一个具有指定值的元素。如下:

vector<int> vec;

fill_n(back_insert(vec),10,0)

这样就不会出错,fill_n函数每写入一个值,都会通过back_inserter生成的插入迭代器实现。效果相当于在vec上调用push_back函数,在vec末尾添加10个元素,每个元素的值均为0

5copy算法(写算法

vector<int> ivec;

copy(ilst.begin(),ilst.end(),back_inserter(ivec));

ilst中的所有元素复制给ivec容器中。其实这种效率不高,可在构造新容器的时候用ilst初始化,如:

vector<int> ivec(ilst.begin(),ilst.end());

6replace算法(写算法

带有4个实参,前两个实参是替换时查找的范围,第3个实参是待替换的值,4个实参是替换值,如:

replace(ilst.begin(),ilst.end(),0,42)

ilst容器中寻找0,用42代替。

7replace_copy算法(写算法

如果不想改变原来的序列,则调用replace_copy,这个算法接收第3个迭代器实参,指定保存调整后序列的目标位置。

如:

replace_copy(ilst.begin(),ilst.end(),back_inserter(ivec),0,42);

调用该函数后,ilst没有改变,ivec存储替换后的副本。

8sort排序算法

sort(words.begin(),words.end());

容器中的元素按字典顺序排列。

9unique算法:

适合于排序后的容器,删除相邻的重复元素。算法返回超出无重复的元素范围末端的下一位置。

如:

vector<string>::iterator end_unique = unique(words.begin(),words.end());

words.erase(end_unique,words.end());

(10)stable_sort算法

sort算法在给定的范围内,按照元素的从小到大排列元素。而stable_sort算法,增加了一个参数,称为谓词,用来控制根据什么原则排序。

如:bool IsShort(const string &s1, const string &s2)

{

return s1.size()<s2.size();

}

stable_sort(words.begin(),words.end(),IsShort);

则是根据元素(字符串)的长短来排序。

11count_if算法

记录满足某个条件的元素在容器中的数目,也需要谓词来说明规则。

如:bool GT6(const string &s)

{

return s.size()>=6;

}

vector<string>::size_type wc = count_if(words.begin(),words,end(),GT6);

小结:

容器和算法库是标准库的基础。标准库定义了超过100个算法,幸运的是,这些算法具有相同的结构,使他们更容易学习和使用。

算法和类型无关,他们通常在一个元素序列上操作,这些元素可以存储在标准容器类型,内置数组甚至是生成的序列上。

算法基于迭代器操作,从而实现类型无关性。

大多数算法使用一对指定元素范围的迭代器作为其头两个实参,其它的迭代器实参包括指定输出目标的输出迭代器,或者用于指定第二个输入序列的另一个或一对迭代器。

查找某个值的算法通常提供第二个版本,用于查找使谓词返回非零值的元素。对于这种算法,第二个版本的函数名字已_if后缀表示。类似的,很多算法提供所谓的复制版本,将(修改过的)元素写到输出序列上,而不是写回输入范围,这种版本的名字已_copy结束。