• 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::
  • 相关阅读:
    NDK开发之ndk-build命令详解
    NDK开发之Application.mk文件详解
    Unity3D自己常用代码
    投资股权众筹项目,至少需要关注6个方面
    2015,我的投资理财策略(股权众筹+P2P网贷+活期理财)
    2015,我的投资理财策略(股权众筹+P2P网贷+活期理财)
    关于weight属性使用的一些细节
    xtu summer individual 5 F
    BNUOJ 1268 PIGS
    BNUOJ 2105 Distance Queries
  • 原文地址:https://www.cnblogs.com/mmmmmmmmm/p/14848913.html
Copyright © 2020-2023  润新知