2013-03-23 87 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 
}