簡體   English   中英

C ++ STL設置lower_bound錯誤結果

[英]C++ STL set lower_bound wrong result

我對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。

怎么了 ?

預期結果是15,但實際結果是33。

不,預期的結果是20,因為函數“返回指向范圍[first,last]中的第一個元素的迭代器,它不會比較小於val。”,因為您可以在std::lower_bound引用中讀取。

你不會得到這個結果,因為你在setCompareFunctorAux結構中使用<=而不是<

結果,當你搜索20時,它會從平等中感到困惑,並在搜索時走向錯誤的方向。


PS:與您的問題無關,但setCompareFunctor不是有效的比較器,因為它不滿足嚴格的弱排序。 為此,只需將<=更改為< 閱讀更多運算符<和嚴格的弱排序

集合的順序必須像< ,而不是<= 由於你有一個元素與你正在尋找的鍵, <=是錯誤的並以錯誤的方式發送搜索。

同時,在set上使用std::lower_bound是浪費的:迭代器不公開搜索結構,因此搜索實際上是線性的。 如果定義setCompareFunctorAux ::is_transparent則可以使用C ++ 14的異構比較來避免這種setCompareFunctorAux ::is_transparent

您必須使用嚴格的較少運算符來自C ++ 2017標准(28.7排序和相關操作)

3對於所有采用Compare的算法,有一個版本使用operator <代替。 也就是說,comp(* i,* j)!= false默認為* i <* j!= false。 對於28.7.3中描述的算法以外的算法,comp應該對值產生嚴格的弱排序

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

考慮到在被調用的算法中使用了運算符

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

我想你正在努力實現與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 ,正如其他響應者已經指出的那樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM