find、find_if、find_first_of、find_if_not、search、二分查找

1.std::find:搜索等于 value 的元素

中文标准库:find、find_if、find_if_not

  • 可能的实现:
template<class InputIt, class T>
InputIt find(InputIt first, InputIt last, const T& value)
{
    for (; first != last; ++first) 
    {
        if (*first == value) 
        {
            return first;
        }
    }
    return last;
}

2.std::find_if:搜索函数对象 p 对其返回 true 的元素,返回值是一个迭代器

  • 注意:函数对象p必须可以返回值true(如果所有元素都不能使其返回true,则没有查找到符合条件的元素)

  • 可能的实现:

template<class InputIt, class UnaryPredicate>
InputIt find_if(InputIt first, InputIt last, UnaryPredicate p)
{
    for (; first != last; ++first) 
    {
        if (p(*first)) 
        {
            return first;
        }
    }
    return last;
}

3.std::find_if_not搜索函数对象 q 对其返回 false 的元素。

  • 可能的实现:
template<class InputIt, class UnaryPredicate>
InputIt find_if_not(InputIt first, InputIt last, UnaryPredicate q)
{
    for (; first != last; ++first) 
    {
        if (!q(*first)) 
        {
            return first;
        }
    }
    return last;
}

4.std::find_first_of:在范围 [first, last) 中搜索范围 [s_first, s_last) 中的任何元素。

中文标准库:find_first_of

  • 注意:两个容器的类型可以不一样,查找到即返回对应元素的迭代器(后面的元素不会再比较),如下示例

  • 算法库中没有find_last_of、find_first_not_of、find_last_not_of这几个函数都是std::string的成员函数

  • 可能的实现版本1:

template<class InputIt, class ForwardIt>
InputIt find_first_of(InputIt first, InputIt last,ForwardIt s_first, ForwardIt s_last)
{
    for (; first != last; ++first) 
    {
        for (ForwardIt it = s_first; it != s_last; ++it) 
        {
            if (*first == *it) 
            {
                return first;
            }
        }
    }
    return last;
}
  • 可能的实现版本2
template<class InputIt, class ForwardIt, class BinaryPredicate>
InputIt find_first_of(InputIt first, InputIt last,ForwardIt s_first, ForwardIt s_last,BinaryPredicate p)
{
    for (; first != last; ++first) 
    {
        for (ForwardIt it = s_first; it != s_last; ++it) 
        {
            if (p(*first, *it)) 
            {
                return first;
            }
        }
    }
    return last;
}
  • 示例:
#include <algorithm>
#include <iostream>
#include <vector>
#include <list>

int main()
{
    std::vector<int> v{ 0, 4,2, 3, 25, 5 };
    std::list<int> t{ 6, 19, 10, 3 };

    //在v中查找第一个和t中任意一个元素相等的元素,没有找到返回v.end()
    auto ret1 = std::find_first_of(v.begin(), v.end(), t.begin(), t.end());  //元素3对应的迭代器
    //在v中查找第一个使二元函数对象(另一个二元函数对象的参数为t中的任意一个元素)返回true的元素,没有找到返回v.end()
    auto ret2 = std::find_first_of(v.begin(), v.end(), t.begin(), t.end(), [](int i, int j) {return i > j; }); //元素4对应的迭代器
    
    return 0;
}

5.find_end:在范围 [first, last - (s_last - s_first)) 中搜索子序列 [s_first, s_last) 的最后一次出现。

  • 该函数依赖std::serach

  • 可能的实现版本1:

template<class ForwardIt1, class ForwardIt2>
ForwardIt1 find_end(ForwardIt1 first, ForwardIt1 last,ForwardIt2 s_first, ForwardIt2 s_last)
{
    if (s_first == s_last)
        return last;
    ForwardIt1 result = last;
    while (true) 
    {
        ForwardIt1 new_result = std::search(first, last, s_first, s_last);
        if (new_result == last) 
            break;
        else 
        {
            result = new_result;
            first = result;
            ++first;
        }
    }
    return result;
}
  • 可能的实现版本2:
template<class ForwardIt1, class ForwardIt2, class BinaryPredicate>
ForwardIt1 find_end(ForwardIt1 first, ForwardIt1 last,ForwardIt2 s_first, ForwardIt2 s_last,BinaryPredicate p)
{
    if (s_first == s_last)
        return last;
    ForwardIt1 result = last;
    while (true) 
    {
        ForwardIt1 new_result = std::search(first, last, s_first, s_last, p);
        if (new_result == last)
            break;
        else 
        {
            result = new_result;
            first = result;
            ++first;
        }
    }
    return result;
}

6.std::search:搜索范围 [first, last - (s_last - s_first)) 中元素子序列 [s_first, s_last) 的首次出现。

  • 可能的实现1:
template<class ForwardIt1, class ForwardIt2>
ForwardIt1 search(ForwardIt1 first, ForwardIt1 last,ForwardIt2 s_first, ForwardIt2 s_last)
{
    for (; ; ++first) 
    {
        ForwardIt1 it = first;
        for (ForwardIt2 s_it = s_first; ; ++it, ++s_it) 
        {
            if (s_it == s_last)
                return first; //第二个容器遍历完了,说明找到了子序列[s_first,s_last),返回子序列第一个元素在第一个容器中的位置
            if (it == last)
                return last;  //第一个容器遍历完了,说明没找到子序列,返回第一个容器的end()
            if (!(*it == *s_it))
                break;//两个容器中的当前要比较的元素不相等,第一个容器要查找的位置加1然后继续比较
        }
    }
}
  • 可能的实现2:
template<class ForwardIt1, class ForwardIt2, class BinaryPredicate>
ForwardIt1 search(ForwardIt1 first, ForwardIt1 last,ForwardIt2 s_first, ForwardIt2 s_last,BinaryPredicate p)
{
    for (; ; ++first) 
    {
        ForwardIt1 it = first;
        for (ForwardIt2 s_it = s_first; ; ++it, ++s_it) 
        {
            if (s_it == s_last)
                return first;
            if (it == last)
                return last;
            if (!p(*it, *s_it))
                break;
        }
    }
}
  • std::search_n:在范围 [first, last) 中搜索 count 个相同元素的序列,每个都等于给定的值 value 。内部使用了equal_to

示例代码:

#include <algorithm>
#include <iostream>
#include <vector>
#include <list>

int main()
{
    std::vector<int> v{ 0, 4, 2, 3, 25, 5, 2, 3, 25 };

    std::list<int> x{ 2, 3, 25 };
    std::list<int> y{ 3 ,5 ,3};

    auto ret1 = std::find_first_of(v.begin(), v.end(), x.begin(), x.end());
    std::cout << *(--ret1);  //4
    auto ret2 = std::find_first_of(v.begin(), v.end(), y.begin(), y.end());
    std::cout << *(--ret2);  //2

    auto ret3 = std::search(v.begin(), v.end(), x.begin(), x.end());
    std::cout << *(--ret3);  //4
    auto ret4 = std::search(v.begin(), v.end(), y.begin(), y.end());    //end()

    auto ret5 = std::find_end(v.begin(), v.end(), y.begin(), y.end());  //end()
    auto ret6 = std::find_end(v.begin(), v.end(), x.begin(), x.end());
    std::cout << *(--ret6);  //5

    std::vector<int> v1{ 0,1,0,0,2,0,0,0,3,0,0,0,3,0,0,0,0,4 };
    std::list<int> z{ 0,0,0 };

    auto ret7 = std::search_n(v1.begin(), v1.end(), 3, 0);
    std::cout << *(--ret7);  //2
    //上下两中方式等价
    auto ret9 = std::search(v1.begin(), v1.end(), z.begin(), z.end());
    std::cout << *(--ret9);  //2

    return 0;
}

7.其他查找(比较)算法

函数 描述
std::includes 已排序范围 [first2, last2) 是已排序范围 [first1, last1) 的子序列则返回 true 。(子序列不必相接。)
std::adjacent_find 查找首对相邻的相同(或满足给定谓词的)元素
std::mismatch 寻找两个范围出现不同的首个位置,返回来自两个范围:一个以 [first1, last1) 定义而另一个以 [first2,last2) 定义,的首个不匹配对
std::equal 确定两个元素集合是否是相同的,如果范围 [first1, last1) 和范围 [first2, first2 + (last1 - first1)) 相等,返回 true ,否则返回 false

8.二分查找

使用二分查找的容器必须按升序排序

  • binary_search:查找某个元素是否出现

在数组中以二分法检索的方式查找,若在数组(要求数组元素非递减)中查找到元素则真,若查找不到则返回值为假。

vector<int> vec{ 9,8,7,6,5,4,3,2,1 };
auto ret = binary_search(vec.begin(), vec.end(), 2);  //false,
  • lower_bound 查找第一个大于或等于某个元素的位置

  • upper_bound 查找第一个大于某个元素的位置

  • equal_range 查找等于某值的元素范围
    返回值是pair<iterator,iterator>

vector<int> vec{ 1,2,2,2,4,4,4,5,7,8 };
auto ret1 = equal_range(vec.begin(), vec.end(), 3);  //找不到则返回两个相同的第一个大于3的位置{4,4}
auto ret2 = equal_range(vec.begin(), vec.end(), 4);  //返回第一个等于4和第一个大于4的位置{4,5}
  • equal_rangeC++20新增三个ranges::
posted @ 2021-06-04 11:36  滴哒哒哒  阅读(21)  评论(0编辑  收藏  举报