Range作为map的Key

Range 作为 map Key

当自定义的数据作为 STL map Key 时,需要编写自定义比较函数。(通常是小于函数)该函数用来比较 Key 的排序先后关系。

如果函数返回 true ,说明 left 小于 right

但是如果返回 false ,那么 map 会交换参数并再次调用比较函数,如果返回 true ,说明 right 小于 left ,如果也返回 false ,那么说明 left right 等价( equivalence )。

注意调用 map find 时,使用的并非直观的 == 运算符。而是 !(left < right) && !(right < left) ,在自己编写比较函数时,这一点要特别注意。但是调用 algorithm find 是,使用的是 == 运算符。

如果现在想以某个 Range 作为 Key ,那么该如何实现比较函数呢。(只要 key Range map 某个 Range 内就认为找到)

一. 如果 Range 是连续的。

比如 [0, 20) , [20, 100), [100, 200) 等等(使用的是前闭后开区间表示法),那么其实只要把 Range 的开始位置作为 Key 就可以了。 find 时,自己编写 find 函数就可以了。

find 的逻辑如下: iterator find ( map , key )

如果 iterator->key >= key && (iterator+1)->key < key ,那么就返回 iterator 。当然如果 iterator+1 == map.end() ,那么也返回 iterator 就好了。详细的不再描述。

二. 如果 Range 是不连续的。

但是,如果 Range 是不连续的,比如 [0, 10) , [20, 50), [100, 200) 等等,那么就有必要自己做一个数据类型作为 Key 了。并为该类型重载 < 运算符。当然不重载该运算符也可以,写一个小于函数对象,将该类型作为 map 的第三个模板参数也可以。

三. 如果将 Range 放在 vector 中,并调用 find 进行查找时,那么就需要重载 == 运算符。如果基于 Equivalence 的话,该运算符可以用 < 运算符来实现。如果是基于 equality 的话,就要严格比较 Range 的开始结束位置。当然不重载该运算符也可以,写一个比较函数对象,将该类型的一个对象作为 find_if 的第四个参数即可。


 

四. 示例代码如下:

typedef struct stRange

{

    // [ nBegin, nEnd )

       int   nBegin;

       int   nEnd;

       stRange( int nPos = 0 )

       {

              nBegin = nEnd = nPos ;

       }

       stRange( int nLeft , int nRight )

       {

              nBegin = nLeft ;

              nEnd   = nRight;

       }

}stRange;

 

inline bool operator < ( const stRange & lh , const stRange & rh )

{

         // [lh.nBegin, lh.nEnd), [rh.nBegin, rh.nEnd)

       if ( lh.nBegin < rh.nBegin && lh.nEnd <= rh.nBegin)

       {

              return true ;

       }

       [rh.nBegin, rh.nEnd), [lh.nBegin, lh.nEnd)

       //else if ( lh.nBegin >= rh.nEnd && lh.nEnd > rh.nEnd)

       //{

       //     return false ;

       //}

       return false ;

}

 

// Equivalence-based

inline bool operator == (const stRange & lh , const stRange & rh )

{

       return !(lh < rh) && !(rh < lh) ;

}

 

Equality-based

//inline bool operator == (const stRange & lh , const stRange & rh )

//{

//     return (lh.nBegin == rh.nBegin) && (lh.nEnd == rh.nEnd) ;

//}


 

测试代码如下:

 

#include <map>

#include <vector>

#include <algorithm>

using std::map ;

using std::vector ;

 

void TestRange()

{

       map< stRange , int > mr ;

       mr[stRange(0,10)] = 1 ;

       mr[stRange(10,20)] = 2 ;

       mr[stRange(20,50)] = 5 ;

       mr[stRange(50,100)] = 10 ;

       mr[stRange(200,1000)] = 100 ;

       mr[stRange(3000,10000)] = 1000 ;

       mr[stRange(11111,22222)] = 2222 ;

 

       ASSERT( mr[stRange(4)] == 1 ) ;

       ASSERT( mr[stRange(10)] == 2 ) ;

       ASSERT( mr[stRange(40)] == 5 ) ;

       ASSERT( mr[stRange(99)] == 10 ) ;

       ASSERT( mr.end() == mr.find(stRange(100)) ) ;

       ASSERT( mr.end() == mr.find(stRange(150)) ) ;

       ASSERT( mr[stRange(400)] == 100 ) ;

       ASSERT( mr[stRange(4000)] == 1000 ) ;

       ASSERT( mr.end() == mr.find(stRange(40000)) ) ;

 

       // vector

       vector<stRange > vr ;

       vr.push_back(stRange(0,10)) ;

       vr.push_back(stRange(10,20)) ;

       vr.push_back(stRange(20,50)) ;

       vr.push_back(stRange(50,100)) ;

       vr.push_back(stRange(200,1000)) ;

       vr.push_back(stRange(3000,10000)) ;

       vr.push_back(stRange(11111,22222)) ;

 

       ASSERT ( std::find( vr.begin() , vr.end() , stRange(4) )->nBegin   == 0 ) ;

       ASSERT ( std::find( vr.begin() , vr.end() , stRange(10) )->nBegin   == 10 ) ;

       ASSERT ( std::find( vr.begin() , vr.end() , stRange(40) )->nBegin   == 20 ) ;

       ASSERT ( std::find( vr.begin() , vr.end() , stRange(99) )->nBegin   == 50 ) ;

       ASSERT ( std::find( vr.begin() , vr.end() , stRange(100) )          == vr.end() ) ;

       ASSERT ( std::find( vr.begin() , vr.end() , stRange(150) )          == vr.end() ) ;

       ASSERT ( std::find( vr.begin() , vr.end() , stRange(400) )->nBegin  == 200 ) ;

       ASSERT ( std::find( vr.begin() , vr.end() , stRange(4000) )->nBegin == 3000 ) ;

       ASSERT ( std::find( vr.begin() , vr.end() , stRange(40000) )        == vr.end() ) ;

}

 

五. 备注:

map key 有多个排序条件时(第一排序条件,第二排序条件),那么比较函数首先比较第一排序条件,在第一排序条件相同的条件比较第二排序条件。在第二排序条件相同的条件下比较第三排序条件,以此类推。

示例代码如下。

inline bool operator < ( const CompKey & lh , const CompKey & rh )

{

    if ( lh.firstComp < rh.firstComp )

    {

        return true ;

    }

    else if ( lh.firstComp == rh.firstComp )

    {

        return lh.secondComp < rh.secondComp ;

    }

    return false ;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值