STL: unordered_map 自定義鍵值類型的使用

當試圖使用自定義類型作爲 unordered_map 的鍵值時,則必須爲自定義類型定義 Hash 函數與相等的判斷條件。我們先定義自定義類型作鍵值,代碼如下:

struct KEY
{
    int first;
    int second;
    int third;
 
    KEY(int f, int s, int t) : first(f), second(s), third(t){}
};
    1. Hash 函數
    必須爲 override 了 operator() 的一個類,一般自定義類型可能包含幾種內置類型,我們可以分別計算出內置類型的 Hash Value 然後對它們進行 Combine 得到一個哈希值,一般直接採用移位加異或(XOR)便可得到還不錯的哈希值(碰撞不會太頻繁),如下:

struct HashFunc
{
    std::size_t operator()(const KEY &key) const 
    {
        using std::size_t;
        using std::hash;
 
        return ((hash<int>()(key.first)
            ^ (hash<int>()(key.second) << 1)) >> 1)
            ^ (hash<int>()(key.third) << 1);
    }
};


    另外一種方法是直接實例化模板,這樣的話使用 unordered_map 時便不用再指定 Hash 函數,但要求必須爲 KEY 重載 operator ==,實例化模板如下:


namespace std 
{
    template <>
    struct hash<KEY>
    {
        std::size_t operator()(const KEY &key) const
        {
            using std::size_t;
            using std::hash;
 
            // Compute individual hash values for first,
            // second and third and combine them using XOR
            // and bit shifting:
 
            return ((hash<int>()(key.first)
                ^ (hash<int>()(key.second) << 1)) >> 1)
                ^ (hash<int>()(key.third) << 1);
        }
    };
}

    2. 相等函數
    哈希需要處理碰撞,意味着必須得知道兩個自定義類型對象是否相等,所以必須得提供比較相等的方法,可以 overload operator ==,可以用 std::equal,也可以實現一個 override operator () 的類,這裏我們採用後者(這也意味着 Hash 函數不能使用實例化模板的方法,只能定義一個重載了 operator() 的類),代碼如下:

struct EqualKey
{
    bool operator () (const KEY &lhs, const KEY &rhs) const
    {
        return lhs.first  == rhs.first
            && lhs.second == rhs.second
            && lhs.third  == rhs.third;
    }
};

    3. 應用實例
    下面爲一個具體應用的例子

int main()
{
    unordered_map<KEY, string, HashFunc, EqualKey> hashmap =
    {
        { { 01, 02, 03 }, "one" },
        { { 11, 12, 13 }, "two" },
        { { 21, 22, 23 }, "three" },
    };
 
    KEY key(11, 12, 13);
 
    auto it = hashmap.find(key);
    
     if (it != hashmap.end())
     {
         cout << it->second << endl;
     }
 
    return 0;
}

 

轉自:https://blog.csdn.net/zhangpiu/article/details/49837387

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章