std :: map lower_bound没有返回正确的值

时间:2011-03-21 17:10:52

标签: c++ linux stl

下午好,我正在尝试使用std :: map lower_found成员函数。但是,它一直回答错误的答案。这是我的测试代码的摘录。请向我解释如何正确制作std :: map下界功能。谢谢。

class Interval { 
     public:   
         explicit Interval(int item){ 
            mLow = item;
            mHigh = item;
            mStamp = 0;
         }
         Interval(int low, int high, int stamp = 0){ 
            mLow = low;
            mHigh = high;
            mStamp = stamp;

         }
         Interval(void){  
            mLow = 0;
            mHigh = 0;
            mStamp = 0;

         }

         Interval(const Interval& r):
            mLow(r.mLow),
            mHigh(r.mHigh),
            mStamp(r.mStamp)
         {

         }

         bool operator<(const Interval& rhs) const{     
             if (mLow < rhs.mLow){             
                 return true;     
             }     
             return false;   
         } // operator<    
         int low() const { return mLow; }   
         int high() const { return mHigh; }
         int getStamp() const { return mStamp; }
         void setLow(int lower) { mLow = lower; }   
         void setHigh(int higher) { mHigh = higher; }
         void setStamp(int stamp) { mStamp = stamp; }
     private:   
         int mLow;   
         int mHigh; 
         int mStamp;
}; // class Interval 


 int main(int Argc_,char *Argv_[]) {
    int n;
    Interval r;

    std::map<Interval, Interval> Intervals_type;
    r.setLow(0);
    r.setHigh(10);
    r.setStamp(1);
    std::pair< Interval, Interval > tmp(r,r);
    Intervals_type.insert(tmp); 

    r.setLow(10);
    r.setHigh(20);
    r.setStamp(2);
    std::pair< Interval, Interval > tmp2(r,r);
    Intervals_type.insert(tmp2);    


    r.setLow(20);
    r.setHigh(30);
    r.setStamp(3);
    std::pair< Interval, Interval > tmp3(r,r);
    Intervals_type.insert(tmp3);    

    r.setLow(30);
    r.setHigh(40);
    r.setStamp(4);
    std::pair< Interval, Interval > tmp4(r,r);
    Intervals_type.insert(tmp4);    



    n = 36;
    std::map<Interval, Interval>::const_iterator it = 
               Intervals_type.lower_bound(Interval(n));
    if (it == Intervals_type.end()){
        printf(" n = %d not found\n",n);
    }

    return 1;
}

4 个答案:

答案 0 :(得分:3)

std::map仅与operator <进行比较,因此它只知道Interval::mLow,有效地将所有区间视为[mLow,∞]。你使用的是错误的容器。它可以用地图来做,但它更难。请改用Boost.Icl

编辑:为此目的,STL中最好的东西是std :: multi_set。通过正确的终点订购您的间隔:

     bool operator<(const Interval& rhs) const{     
         return mHigh < rhs.mHigh;
     }

现在你可以这样做:

std::multi_set<Interval> cont;
cont.insert(Interval(0,10,1));
cont.insert(Interval(10,20,2));
cont.insert(Interval(20,30,3));
cont.insert(Interval(30,40,4));

std::multi_set<Interval>::const_iterator iter = cont.lower_bound(Interval(36));
if(iter == cont.end() || iter->low() > 36)
    // not found
else
    // found

答案 1 :(得分:2)

IIUC,你正在处理范围,你有一个不变的 范围不重叠的地图。如果是这样的话,你就有了 定义您的运营商&lt;所以它处理范围,并且确实如此 一些激烈的(断言失败或例外) 重叠的情况,以防止插入这样的范围。 假设半开放范围[低,高]和断言 Interval的构造函数中的高&gt; =低,类似于 以下应该有效:

struct CmpInterval
{
    //  For insertion...
    bool operator<( Interval const& lhs, Interval const& rhs) const
    {
        assert( lhs.low >= rhs.high
                || lhs.high <= rhs.low
                || (lhs.low == rhs.low && lhs.high == rhs.high) );
        return lhs.low < rhs.low;
    }
    //  For find, lower_bound, etc.
    bool operator<( Interval const& lhs, int target ) const
    {
        return lhs.low < target;
    }

    bool operator<( int target, Interval const& rhs ) const
    {
        return target <= rhs.high;
    }
};

传递时,最后两个用于lower_bound,find等 一个简单的整数作为键(而不是一个Interval);他们在一起 定义int和an之间的严格排序关系 Inteval, IFF 没有重叠的间隔,和 等价关系,使得区间[i,j)中的所有n都是 相当于该范围和彼此。 (再次,如果有的话 是重叠的间隔,没有等价关系, 并且行为未定义。)

答案 2 :(得分:1)

lower_bound应该返回第一个等于或大于的项目之前的位置。地图中最大的项目实际上较小,因此返回结束。

在您的运营商中&lt;你只检查mLow。如果要检查36是否在30到40范围内,请更正您的运营商&lt;。

答案 3 :(得分:1)

lower_bound的定义是它返回一个位置,您可以在其中插入项目并仍然保持容器的排序。您的比较功能仅适用于low成员;你的容器的低价为0,10,20,30。 36用于保持容器分类的唯一插入点就在最后。