简体   繁体   English

C ++ STL设置lower_bound错误结果

[英]C++ STL set lower_bound wrong result

I'm having some issues with the lower_bound comparison function. 我对lower_bound比较函数有一些问题。

I have a set of pairs ordered by the second value of the pair and i'm tryin to get the lower_bound from this set by a value. 我有一对由该对的第二个值排序的对,我试着通过一个值从这个集合中获取lower_bound。

My current code is: 我目前的代码是:

#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;
}

The expected result is 15, but the real result is 33. 预期结果是15,但实际结果是33。

What is wrong ? 怎么了 ?

The expected result is 15, but the real result is 33. 预期结果是15,但实际结果是33。

No, the expected result is 20, since the function "Returns an iterator pointing to the first element in the range [first,last) which does not compare less than val.", as you can read in the std::lower_bound reference. 不,预期的结果是20,因为函数“返回指向范围[first,last]中的第一个元素的迭代器,它不会比较小于val。”,因为您可以在std::lower_bound引用中读取。

You will not get this result, because you use <= instead of < in your setCompareFunctorAux struct. 你不会得到这个结果,因为你在setCompareFunctorAux结构中使用<=而不是<

As a result, when you search for 20, it get confused from the equality, and go towards the wrong direction when searching. 结果,当你搜索20时,它会从平等中感到困惑,并在搜索时走向错误的方向。


PS: Not related to your problem, but setCompareFunctor is not a valid comparator, because it doesn't satisfy the strict weak ordering. PS:与您的问题无关,但setCompareFunctor不是有效的比较器,因为它不满足严格的弱排序。 In order to do so, just change <= to < . 为此,只需将<=更改为< Read more in Operator< and strict weak ordering . 阅读更多运算符<和严格的弱排序

The ordering for a set must act like < , not <= . 集合的顺序必须像< ,而不是<= Since you have an element with the key you're looking for, the <= is wrong and sends the search the wrong way. 由于你有一个元素与你正在寻找的键, <=是错误的并以错误的方式发送搜索。

Meanwhile, using std::lower_bound on a set is wasteful: the iterators don't expose the search structure, so the search is effectively linear. 同时,在set上使用std::lower_bound是浪费的:迭代器不公开搜索结构,因此搜索实际上是线性的。 You can avoid this with C++14's heterogeneous comparisons if you define setCompareFunctorAux ::is_transparent . 如果定义setCompareFunctorAux ::is_transparent则可以使用C ++ 14的异构比较来避免这种setCompareFunctorAux ::is_transparent

You have to use the strict less operator From the C++ 2017 Standard (28.7 Sorting and related operations) 您必须使用严格的较少运算符来自C ++ 2017标准(28.7排序和相关操作)

3 For all algorithms that take Compare, there is a version that uses operator< instead. 3对于所有采用Compare的算法,有一个版本使用operator <代替。 That is, comp(*i, *j) != false defaults to *i < *j != false. 也就是说,comp(* i,* j)!= false默认为* i <* j!= false。 For algorithms other than those described in 28.7.3, comp shall induce a strict weak ordering on the values . 对于28.7.3中描述的算法以外的算法,comp应该对值产生严格的弱排序

4 The term strict refers to the requirement of an irreflexive relation (!comp(x, x) for all x), and the term weak to requirements that are not as strong as those for a total ordering, but stronger than those for a partial ordering... 4严格一词指的是一种反自由关系的要求(对所有x都是!comp(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);
    }
};

Take into account that within the called algorithm there is used the operator 考虑到在被调用的算法中使用了运算符

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

};

Here is a demonstrative program 这是一个示范计划

#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;
}

Its output is 它的输出是

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

The expected result is 15, but the real result is 33. 预期结果是15,但实际结果是33。

And the expected and correct result is 20 because there is an element with the second value equal to 20 and you are searching exactly 20. 并且预期和正确的结果是20,因为有一个元素的第二个值等于20,你正在搜索20。

Take into account that the template class std::set has its own member function lower_bound . 考虑到模板类std::set有自己的成员函数lower_bound

I think you are trying to achieve something different from what std::lower_bound can give to you. 我想你正在努力实现与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;
}

outputs 输出

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

Everything seems legitimate as per the documentation provided in http://en.cppreference.com/w/ . 根据http://en.cppreference.com/w/中提供的文档,一切似乎都是合法的。

I assume you are trying to put 6->15 using some trick, and the very same trick breaks std::lower_bound due to the violation of the weak ordering as is already pointed out by the other responders. 我假设您正在尝试使用一些技巧来放置6->15 ,并且由于违反了弱排序,同样的技巧会破坏std::lower_bound ,正如其他响应者已经指出的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM