C++ <algorithm> 中的函数的名字真让人费解,本文旨在对其简单归纳。如果同时满足“传入开始和结束迭代器对象”、“返回之间的一个迭代器对象的”、“不要求序列是排序过后的序列(即复杂度大约是 O(n) 的)”,都视为线性序列查找函数。这样一来, <algorithm> 里的查找函数,有:find, find_if, find_end, find_first_of, adjacent_find, mismatch, search, search_n, …

这篇文章参考了 http://www.cplusplus.com/reference/algorithm/ . 所有示例代码可以到这里找。

1. find, find_if – 查找序列中的指定元素

把这些函数列在一起,是因为这些函数的算法类似,复杂度都是 O(n), 并且给出的“查找目标”是单个元素。

1.1. find – 查找与指定元素相等的元素

最典型的查找,查找“开始和结束迭代器对象之间的”、“第一个出现的”、“某个与给定的值‘相同’的”元素。如果查找的对象没有重载 operator==, 那么就比较两个对象的二进制数据;反之使用重载后的 operator==. 函数原型如下:

template<class InputIterator, class T> InputIterator find
(
    InputIterator first, InputIterator last,
    const T &value
);

1.2. find_if – 查找符合指定条件的元素

条件式查找,查找“开始和结束迭代器对象之间的”、“第一个出现的”、“满足某个条件的”元素。调用这个函数,需要传入一个一元的函数指针函数对象,以便指明“怎样才算满足某个条件”。要传入的函数对象原型与该函数的原型如下:

template<class InputIterator, class Predicate>
InputIterator find_if
(
    InputIterator first, InputIterator last,
    Predicate pred
);
template<class T>
bool pred
(
    const T &value
);

2. find_first_of – 查找序列中最先出现在另一个序列中的元素

这个函数查找的是序列中的单个元素,与 find 和 find_if 不同的是,需要给这个函数的“查找目标”是一组迭代器,这个函数会查找“在第一组迭代器之间”、“最先出现的”、“在另一组迭代器之间的”元素。由于给出的“目标子序列”是被假定成未排序的,所以其复杂度是 O(mn), 其中 m 和 n 分别是两个序列的长度。

3. search, find_end – 查找一个子序列

这些函数的共同点,是查找的都是一个序列中的特定子序列,算法应该都是 KMP, 效率还是相当高的。

3.1. search – 查找第一个出现的子串

函数原型是:

template<class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 search
(
    ForwardIterator1 first1, ForwardIterator1 last1,
    ForwardIterator2 first2, ForwardIterator2 last2
);
template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
ForwardIterator1 search
(
    ForwardIterator1 first1, ForwardIterator1 last1,
    ForwardIterator2 first2, ForwardIterator2 last2,
    BinaryPredicate pred
);
template<class T> bool pred
(
    const T &a,
    const T &b
);

函数的功能是,查找 [first1, last1) 之间的,与 [first2, last2) 匹配的第一个子串;并返回 [first1, last1) 之间的一个迭代器对象,这个对象指向匹配子串中的第一个元素。

3.2. find_end – 查找最后一个出现的子串

这个函数基本上与 search 是一样的,只不过返回的是最后匹配的子串的第一个元素的迭代器对象。就不多说什么了。

4. mismatch – 查找两个序列中最先出现不同的元素

mismatch 能够找出两个几乎相同的序列中,最先出现不同的地方。函数的原型如下:

template<class InputIterator1, class InputIterator2>
pair<InputIterator1, InputIterator2> mismatch
(
    InputIterator1 first1, InputIterator1 last1,
    InputIterator2 first2
);
template <class InputIterator1, class InputIterator2, class BinaryPredicate>
pair<InputIterator1, InputIterator2> mismatch
(
    InputIterator1 first1, InputIterator1 last1,
    InputIterator2 first2,
    BinaryPredicate pred
);

这个函数会返回一个 pair<InputIterator1, InputIterator2> . 这个 pair 中的 first 和 second 分别是前一个序列和后一个序列的迭代器,它们各自指向这两个序列最开始出现不同的地方。

应该可以看出来,由于第二个序列只传入了起始迭代器,即 first2. 所以这个函数不会帮助我们检查第二个序列的溢出情况。所以它要求程序员能够保证第二个序列一定要比第一个“长”,或者它们之间有某个地方出现了不同。

算法的复杂度是 O(n), 其中 n 是第一个序列的长度。

5. adjacent_find, search_n – 查找连续相同的元素

这两个函数的作用都是查找连续相同的元素,然而它们最明显的区别是,adjacent_find 是查找连续两个相同的元素,而 search_n 可以查找任意个连续相同的元素。

5.1. adjacent_find – 查找序列中连续两个相同的元素

比如,序列 1, 2, 3, 3, 4 中连续两个相同的元素是 3, 3. 那么这个函数会返回第一个 3 的迭代器,此之谓“连续两个相同的元素”。函数原型:

template<class ForwardIterator>
ForwardIterator adjacent_find
(
    ForwardIterator first, ForwardIterator last
);
template<class ForwardIterator, class BinaryPredicate>
ForwardIterator adjacent_find
(
    ForwardIterator first, ForwardIterator last,
    BinaryPredicate pred
);

5.2. search_n – 查找序列中连续任意个相同的元素

这个函数和 adjacent_find 的不同,就是能够查找的连续元素个数上的不同。函数原型如下:

template<class ForwardIterator, class Size, class T, class BinaryPredicate>
ForwardIterator search_n
(
    ForwardIterator first, ForwardIterator last,
    Size count, const T& value
);
template<class ForwardIterator, class Size, class T, class BinaryPredicate>
ForwardIterator search_n
(
    ForwardIterator first, ForwardIterator last,
    Size count, const T& value,
    BinaryPredicate pred
);

事实上,如果把 search_n 的 count 参数写成 2, 那么它的效果应该和 adjacent_find 是一样的。

总结

  1. find, find_if - 查找序列中的指定元素
  2. find_first_of - 查找序列中最先出现在另一个序列中的元素
  3. search, find_end - 查找一个子序列
  4. mismatch - 查找两个序列中最先出现不同的元素
  5. adjacent_find, search_n - 查找连续相同的元素

说明 STL 的算法命名还真够混乱的。

以后还要做的事

以后要把 <algorithm> 和其它容器的类似功能横向比较归纳。

原创文章,转载请注明来源:http://euyuil.com/2270/sequencial-search-functions-cpp-algorithm-library/