泛型算法概述
标准库容器定义的操作集合相当的少,顺序容器只定义了添加/删除、查找元素、访问首尾元素、确定容器是否为空和获得首尾迭代器的操作。
而像其他很多有用的操作如:查找特定元素、替换或删除特定值、重排元素顺序等,标准库并未给容器定义成员函数实现这些操作,而是定义了一组泛型算法,可以用于不同类型的元素和多种容器类型。
①算法不直接操作容器而是遍历由两个迭代器指定的一个元素范围来进行操作
大多数算法定义在头文件algorithm中,通常情况下,算法遍历迭代器指定的范围,对其中的一个元素进行处理。
如:有一个int的vector,希望知道vector中是否包含一个特定值。
vector<int> vec{1, 3, 42};
int val = 42;
auto res = find(vec.cbegin(), vec.cend(), val);
cout << "The value " << val
<< (res == vec.cend() ? " is not present" : " is present")
<< endl;
//结果为:The value is present
find函数:
- find函数作用是在一个未排序的元素序列中查找给定值是否在所给范围内。
- find函数用法:find(iter1, iter2, val)。其中iter1和iter2表示一个元素范围的迭代器,第三个参数是一个值。
- find函数的返回值:如果元素范围内有匹配的元素,则返回指向第一个等于给定值的元素迭代器。如果无匹配元素,则返回第二个参数来表示搜索失败。可以通过比较返回值和第二个参数判断是否搜索成功。
由于find操作的是迭代器,因此可以用同样的find函数在任何容器中查找值。
如:在string的list中查找一个给定值
string val = "a value";
list<string> lst{"abc", "bcd", "a value", "akz"};
auto res = find(lst.cbegin(), lst.cend(), val);
cout << "The value " << val
<< (res == lst.cend() ? " is not present" : " is present")
<< endl;
//结果为:The value is present
②算法如何工作
为了弄清算法如何作用于不同类型的容器,我们还是以find为例来观察。find应该执行如下步骤:
- 访问序列中的首元素。
- 比较此元素与我们要查找的值。
- 如果此元素与我们要查找的值匹配,find返回此元素的迭代器。
- 否则,find前进到下一个元素,重复执行步骤2和步骤3
- 如果到达序列尾,find应停止。
- 如果find到达序列末尾,它应该返回一个指出元素未找到的值(第二个参数的迭代器)。此值和步骤3返回值必须具有相容的类型。
可以看出除了第二步需要比较运算符之外,其他步骤都不依赖于容器所保存的元素的类型,只要用迭代器操作就可以完成其他所有操作。
算法只在迭代器上执行操作,不依赖于容器类型和容器保存的元素类型。因此,泛型算法永远不会执行容器操作,只是运行于迭代器上,永远不会改变底层容器的大小。算法可能改变容器中保存的元素,可能在容器内移动元素,但是永远不会直接添加或删除元素。