C++11.1 章 泛型算法---能够作用在不同类型的容器和元素上的算法

简介

  • 标准库没有为每种容器类型都定义实现这些操作的成员函数,而是定义了一组泛型算法:因为实现相同的操作,所以称为“算法”;而“泛型”指的是他们可以操作在多种容器类型上—-vector或list这些标准库类型,还可用在内置数组类型、其他类型的序列。

    • 大多数算法是通过遍历由两个迭代器标记的一段元素类实现其功能。典型情况下,算法在遍历一段元素范围时,操纵其中的每一个元素。

===============================================================================================================================

引言

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

  • 标准容器定义了很少的操作,大部分容器支持(9和10两章):

    • 大部分容器支持添加和删除元素—insert 和erase、clear;
    • 访问第一个和最后一个元素—back 、front;
    • 获取容器的大小,并且在某些情况下重设容器的大小—size、capacity、reserve;
    • 获取指向第一个元素和最后一个元素的下一个位置的迭代器—begin、end
  • 但是用户还希望对容器元素进行更多其他有用的操作:

    • 给顺序容器排序
    • 查找某个特定的元素,查找最大或最小的元素
    • 标准库没有为每种容器类型都定义实现这些操作的成员函数,而是定义了一组泛型算法:因为实现相同的操作,所以称为“算法”;而“泛型”指的是他们可以操作在多种容器类型上—-vector或list这些标准库类型,还可用在内置数组类型、其他类型的序列。
  • 大多数算法是通过遍历由两个迭代器标记的一段元素类实现其功能。典型情况下,算法在遍历一段元素范围时,操纵其中的每一个元素。

一、概述—-find运算

  • 假设有一个int型的vector对象,名为vec,我们想知道其中是否包含某个特定值。用标准库提供的find运算:
//vector容器中用find函数
int search_value=42;
vector<int>::const_iterator result=find(vec.begin(),vec.end(),search_value);//find函数返回迭代器

cout<<“the value”<<search_value<<"is"<<

(result==vec.end())?"is not present":"is present"

    <<endl;
//list容器中用find函数
int search_value=42;
list<int>::const_iterator result=find(vec.begin(),vec.end(),search_value);//find函数返回迭代器

cout<<“the value”<<search_value<<"is"<<

(result==vec.end())?"is not present":"is present"

    <<endl;
//由于指针的行为与作用在内置数组上的迭代器一样,因此也可以使用find来搜索数组

int ia[6]={27,210,12,47,109,83};
int search_value=83;
int *result=find(ia,ia+6,search_value);
cout<<(result==ia+6?"not":"is")
    <<endl;

1.算法如何工作—–find 操作必须包含的步骤

  • 每个泛型算法的实现都独立于单独的容器,这些算法还是大而不全的,并且不依赖于容器存储的元素类型。为了知道算法如何工作,让我们来深入了解下find操作。该操作的任务是在一个未排序的元素集合中查找特定的元素。find必须包含以下步骤:

    • (1) 顺序检查每个元素;
    • (2)如果当前元素等于要查找的值,那么返回指向该元素的迭代器。
    • (3)否则,检查下一个元素,重复步骤2,直到找到这个值,或者检查完所有的元素为止。
    • (4)如果已经到底集合末尾,而且还未找到该值,则返回某个值,指明要查找的值在这个集合中不存在。

2.标准算法固有地独立于类型—-find 操作

  • 这种算法与容器类型无关,没有任何内容依赖于容器类型。只在一点上隐式地依赖元素类型:必须能够对元素做比较运算。

  • find 操纵的算法的明确要求如下

  • (1)需要某种遍历集合的方式:能够从一个元素向前移动到下一个元素。

  • (2)必须能够知道是否到达了集合的末尾
  • (3)必须能够对容器中的每一个元素与被查找的元素进行比较
  • (4)需要一个类型来指出元素在容器中的位置,或者表示找不到该元素

3.迭代器将算法和容器绑定起来—-find 操作

  • 泛型算法用迭代器来解决第一个要求:遍历容器。

    • 所有迭代器都支持自增操作符,从一个元素定位到下一个元素,并提供解引用操作符访问元素的值。

      • 迭代器还支持相等和不等操作,用于判断两个迭代器是否相等
    • 大多数情况下,每个算法都需要使用(至少)两个迭代器来指出该算法操纵的元素范围。第一个迭代器指向第一个元素,第二个迭代器则指向最后一个元素的下一个位置。第二个迭代器所指向的元素【超出末端迭代器】本身不是要操作的元素,而是被用作终止遍历的哨兵。

    • 使用超出末端迭代器还可以很方便地处理第四个要求,只要以此迭代器为返回值,即可表示没有找到要查找的元素。如果要查找的值没有找到,则返回末端迭代器;否则,返回的迭代器指向匹配的元素。

  • 第三个要求—-元素值得比较,有两种解决方法。默认情况下,find操作要求元素类型定义了相等(==)操作符,算法使用这个操作符比较元素,如果元素类型不支持相等(==)操作符,或者打算用不同的测试方法比较元素,则可使用第二个版本的find函数,这个版本需要一个额外的参数:实现元素比较的函数名字。

  • 这些算法从不使用容器操作,因而其实现与类型无关,元素的所有访问和遍历都通过迭代器实现。

  • 标准库提供了超过100种算法,与容器一样,算法有着一致的结构。附录根据操作分类列出了所有的算法

泛型算法本身从不执行容器操作,只是单独依赖迭代器和迭代器操作实现。算法基于迭代器及其操作实现,而并非基于容器操作。这个事实在本质上暗示了:使用“普通”的迭代器时,算法从不修改基础容器的大小。算法也许会改变存储在容器中的元素的值,也许会在容器内移动元素,但是,算法从不直接添加或删除元素。

你可能感兴趣的:(泛型算法)