C ++ STL设置lower_bound错误结果

时间:2017-10-21 13:04:18

标签: c++ algorithm function stl lower-bound

我在使用lower_bound比较功能时遇到了一些问题。

我有一对由该对的第二个值排序的对,我试图通过一个值从该集合中获取lower_bound。

我目前的代码是:

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>

using namespace std;

struct setCompareFunctor
{
    bool operator( )( const pair< int, int > &lhs, const pair< int, int > &rhs ) const
    {
        return( lhs.second <= rhs.second );
    }
};

struct setCompareFunctorAux
{
    bool operator( )( const pair< int, int > &lhs, const pair< int, int > &rhs ) const
    {
        return( lhs.second <= rhs.second );
    }

    bool operator( )( const pair< int, int > &lhs, int val ) const
    {
        return( lhs.second <= val );
    }

    bool operator( )( int val, const pair< int, int > &rhs ) const
    {
        return( val <= rhs.second );
    }
};


int main( )
{
    set< pair< int, int >, setCompareFunctor > submultimi;

    submultimi.insert( make_pair( 1, 15 ) );
    submultimi.insert( make_pair( 2, 9 ) );
    submultimi.insert( make_pair( 3, 33 ) );
    submultimi.insert( make_pair( 4, 44 ) );
    submultimi.insert( make_pair( 5, 20 ) );
    submultimi.insert( make_pair( 6, 15 ) );

    set< pair< int, int >, setCompareFunctor >::iterator it = lower_bound( submultimi.begin( ), submultimi.end( ), 20, setCompareFunctorAux( ) );


    cout << ( *it ).second << endl;


    return 0;
}

预期结果是15,但实际结果是33。

有什么问题?

4 个答案:

答案 0 :(得分:5)

  

预期结果是15,但实际结果是33。

不,预期的结果是20,因为函数&#34;返回指向范围[first,last]中第一个元素的迭代器,它不会比val更小。&#34;,因为你可以阅读std::lower_bound参考文献。

您不会得到此结果,因为您在<=结构中使用<而不是setCompareFunctorAux

因此,当你搜索20时,它会从平等中感到困惑,并在搜索时走向错误的方向。

PS:与您的问题无关,但setCompareFunctor不是有效的比较器,因为它不满足严格的弱排序。为此,只需将<=更改为<即可。阅读Operator< and strict weak ordering中的更多内容。

答案 1 :(得分:2)

集合的顺序必须类似于<,而不是<=。由于您的元素包含您要查找的键,因此<=错误并以错误的方式发送搜索。

同时,在std::lower_bound上使用set是浪费的:迭代器不会公开搜索结构,因此搜索实际上是线性的。如果您定义setCompareFunctorAux ::is_transparent,则可以使用C ++ 14 heterogeneous comparisons来避免这种情况。

答案 2 :(得分:1)

您必须使用严格较少的运算符 从C ++ 2017标准(28.7排序和相关操作)

  

3对于所有采用比较的算法,都有一个使用的版本   运营商LT;代替。也就是说,comp(* i,* j)!= false默认为* i&lt; *∫   !=假。对于28.7.3中描述的算法以外的算法,comp   应该对值产生严格的弱排序。

     

4严格一词指的是反自由关系的要求   (!comp(x,x)表示所有x),而术语弱于要求   不像总排序那样强大,但比那些强   对于部分订购...

struct setCompareFunctor
{
    bool operator( )(const pair< int, int > &lhs, const pair< int, int > &rhs) const
    {
        return(lhs.second < rhs.second);
    }
};

struct setCompareFunctorAux
{
    bool operator( )(const pair< int, int > &lhs, const pair< int, int > &rhs) const
    {
        return(lhs.second < rhs.second);
    }

    bool operator( )(const pair< int, int > &lhs, int val) const
    {
        return(lhs.second < val);
    }

    bool operator( )(int val, const pair< int, int > &rhs) const
    {
        return(val < rhs.second);
    }
};

考虑到在被调用算法中使用了运算符

struct setCompareFunctorAux
{
    //...    
    bool operator( )(const pair< int, int > &lhs, int val) const
    {
        return(lhs.second < val);
    }

};

这是一个示范程序

#include <iostream>
#include <set>
#include <algorithm>

int main()
{
    using namespace std;

    struct setCompareFunctor
    {
        bool operator( )(const pair< int, int > &lhs, const pair< int, int > &rhs) const
        {
            return(lhs.second < rhs.second);
        }
    };

    struct setCompareFunctorAux
    {
        bool operator( )(const pair< int, int > &lhs, const pair< int, int > &rhs) const
        {
            return(lhs.second < rhs.second);
        }

        bool operator( )(const pair< int, int > &lhs, int val) const
        {
            return(lhs.second < val);
        }

        bool operator( )(int val, const pair< int, int > &rhs) const
        {
            return(val <= rhs.second);
        }
    };

    set< pair< int, int >, setCompareFunctor > submultimi;

    submultimi.insert(make_pair(1, 15));
    submultimi.insert(make_pair(2, 9));
    submultimi.insert(make_pair(3, 33));
    submultimi.insert(make_pair(4, 44));
    submultimi.insert(make_pair(5, 20));
    submultimi.insert(make_pair(6, 15));

    for (const auto &p : submultimi)
    {
        cout << "{ " << p.first
            << ", " << p.second
            << " } ";
    }
    cout << endl;

    set< pair< int, int >, setCompareFunctor >::iterator it = lower_bound(submultimi.begin(), submultimi.end(), 20, setCompareFunctorAux());

    cout << (*it).second << endl;

    return 0;
}

它的输出是

{ 2, 9 } { 1, 15 } { 5, 20 } { 3, 33 } { 4, 44 }
20
  

预期结果是15,但实际结果是33。

预期和正确的结果是20,因为有一个元素的第二个值等于20,你正在搜索20个。

考虑到模板类std::set有自己的成员函数lower_bound

答案 3 :(得分:0)

我认为你正在努力实现与std::lower_bound可以给你的不同的东西。

#include <algorithm>
#include <iostream>
#include <set>
#include <utility>

using my_key = std::pair<int, int>;

int main(int argc, char *argv[]) {
  auto comp = [](const my_key &l, const my_key &r) {
    return l.second < r.second;
  };
  std::set<my_key, decltype(comp)> submultimi(comp);

  submultimi.insert({1, 15});
  submultimi.insert({2, 9});
  submultimi.insert({3, 33});
  submultimi.insert({4, 44});
  submultimi.insert({5, 20});
  submultimi.insert({6, 15}); // "<=" inside comp will put this pair into the set

  for (const auto &elem : submultimi)
    std::cout << elem.first << " -> " << elem.second << '\n';

  auto it = std::lower_bound(
      submultimi.begin(), submultimi.end(), 20,
      [](const my_key &l, const int &r) { return l.second < r; });

  std::cout << it->second << '\n';

  return 0;
}

输出

2 -> 9
1 -> 15 # note the lack of 6 -> 15 in the set
5 -> 20
3 -> 33
4 -> 44
20

根据http://en.cppreference.com/w/中提供的文档,一切似乎都是合法的。

我假设你试图让6->15使用一些技巧,并且同样的技巧会因为违反弱顺序而中断std::lower_bound,正如其他响应者已经指出的那样。