2013-03-23 239 views
3

std :: map总是根据值对键进行排序。是否可以按照声明上设置的位数进行排序?如何在std :: map声明中声明自定义的排序函数?

我有计数设置位功能:

for(size_t i = 0; i < CHAR_BIT * sizeof value; ++i, value >>= 1) { 
    if ((value & 1) == byteState) ++num_bits; 
    } 

,但我不知道如何申报地图时使用它。

std::map<int, int> myMap = { 
    {1,2}, 
    {3,4}, 
    //... 
} 

我试图把它作为第三个参数在声明<int,int,decltype(countSetBits)>没有运气。

+0

如果它是一个正常的功能,你还必须将它传递给构造函数作为函数指针。 – Pubby 2013-03-23 15:20:27

+3

顺便说一句,gcc有一个很好的[builtins](http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Other-Builtins.html),其中一个'int __builtin_popcount(unsigned int) '返回整数中设置的位数。 – 2013-03-23 15:28:44

回答

4

你需要用你的函数在一个二元运算符,就像这样:

#include <iostream> 
#include <map> 
#include <algorithm> 

int cntBits(int value) { 
    int num_bits=0; 
    for(size_t i = 0; i < 32 ; ++i, value >>= 1) { 
     if ((value & 1) == 1) ++num_bits; 
    } 
    return num_bits; 
} 

struct cntBitsCmp { 
    bool operator()(int a, int b) { 
     return cntBits(a) < cntBits(b); 
    } 
}; 

现在你可以在一个声明中使用cntBitsCmp

std::map<int,int,cntBitsCmp> myMap= { 
    {128,2}, 
    {3,4}, 
    ... 
}; 

这里是一个demo on ideone。它正确地在3之前排序128,因为3有两个位设置,而128只有一个。

+0

你假设32位整数。 'while(i){++ n; i &=i-1;}' – jthill 2013-03-23 16:03:35

+0

@jthill正确。我复制粘贴OP的代码,并修改它以删除常量。我以代码的形式发布了代码,并明白没有人会在没有修改的情况下使用这些代码。 – dasblinkenlight 2013-03-23 16:06:01

1

基本上这可以工作,只要你想:

bool comp(int x , int y){ 
    return __builtin_popcount(x) < __builtin_popcount(y); 
} 
int main(){ 
    bool(*fn_pt)(int,int) = comp; 
    std::map<int, int, bool(*)(int,int) > myMap (fn_pt); 
    myMap[7]=11; 
    myMap[8]=12; 
    cout<<myMap.begin()->first<<endl; // you get 8 instead of 7 
}