【问题标题】:lower_bound to perform binary searchlower_bound 执行二分查找
【发布时间】:2015-05-20 14:12:26
【问题描述】:

这里我使用std::lower_bound() 创建了一个二分查找函数。如下所示。如果我通过std::pair,这工作正常,但是我只想对pair 的第一个值执行二进制搜索。我认为在lower_bound()Comp 参数中可以做到这一点,但不完全确定如何。

即我的向量如下所示。

std::vector<std::pair<int,double>> v;

我只想比较第一个值,即int

template<class ForwardIt, class T>
ForwardIt binary_searcht(ForwardIt first, ForwardIt last, const T& value)
{
    ForwardIt i = std::lower_bound(first, last, value);
    if (i != last && !(value < *i))
        return i;
    else
        return last;

}

【问题讨论】:

  • 在类型已知的情况下,为什么要将函数定义为模板?这只会使问题复杂化。
  • @MarkRansom 因为我需要返回一个迭代器。正常二进制搜索返回一个布尔值
  • 几个注意事项:1) lower_bound 期望 vector 预先排序(匹配比较函数),2) 标准库支持比较 pairs - a &lt; b if a.first &lt; b.firsta.first == b.first &amp;&amp; a.second &lt; b.second - 因此您可以使用 i = std::lower_bound(first, last, { value.first, std::numeric_limits&lt;double&gt;::min() }); 而不定义自己的比较(但我怀疑它会被 NaN 抛出)。

标签: c++ binary-search


【解决方案1】:

您需要像在std::lower_bound 中那样将比较类添加到您的函数中:

template<class ForwardIt, class T, class Compare>
ForwardIt binary_searcht(ForwardIt first, ForwardIt last, const T& value, Compare cmp)
{
    ForwardIt i = std::lower_bound(first, last, value, cmp);
    if (i != last && !cmp(value, *i))
        return i;
    else
        return last;

}

typedef std::pair<int,double> mypair;
std::vector<mypair> v;
auto f = binary_searcht( v.begin(), v.end(), value, 
    []( const mypair &p1, const mypair &p2 ) { return p1.first < p2.first; } );

【讨论】:

    【解决方案2】:

    std::lower_bound的第二个定义是:

    template< class ForwardIt, class T, class Compare >
    ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value, Compare comp );
    

    因此,您可以编写自己的比较对的函数并使用它。您的模板函数将如下所示:

    template<class ForwardIt, class T, class Compare>
    ForwardIt binary_searcht(ForwardIt first, ForwardIt last, const T& value, Compare comp)
    {
        ForwardIt i = std::lower_bound(first, last, value, comp);
        if (i != last && !(value < *i))
            return i;
        else
            return last;
    }
    

    而且,如果你想将它用于std::vector&lt; std::pair&lt;int,double&gt; &gt;的元素,你应该这样调用它:

    bool compare(std::pair<int, double> a, std::pair<int, double> b) {
        return a.first < b.first;
    }
    binary_searcht(v.begin(), v.end(), value, compare);
    

    或者,如果你想拥有一个干净的代码并且不想声明额外的函数,那么以极客 -std=c++11 的方式使用 lambda 表达式:

    typedef std::pair<int, double> tuple2;
    auto result = binary_searcht(v.begin(), v.end(), 
        [](tuple2 &a, tuple2 &b) { return a.first < b.first; } );
    

    【讨论】:

    • @TonyD 哦,感谢您的建议,我已将名称编辑为 tuple2
    • 感谢这一点,我唯一需要做的改变是我必须做!((value.first &lt; i)),因为我只想考虑第一个值/
    【解决方案3】:

    使用自定义比较函数comp并与std::lower_bound一起使用

    bool comp( std::pair<int , double> &x , std::pair<int , double> &y)
    {
         return x.second < y.second;
    }
    std::lower_bound(v.begin(),v.end(),value, comp);
    

    【讨论】:

    • 有独立函数std::lower_bound,为什么说他要创建std::set
    • @Slava 我提到了std::set:lower_bound 的页面并感到困惑。更正了答案。
    猜你喜欢
    • 2019-12-25
    • 1970-01-01
    • 2012-01-15
    • 2021-04-04
    • 1970-01-01
    • 2018-04-07
    • 2015-12-10
    • 1970-01-01
    相关资源
    最近更新 更多