C++ map和unordered_map自定義key

1、map

1)最簡單的方法就是實現該自定義類型的<操做符,代碼以下:

class Foo
{
public:
    Foo(int num_)
        : num(num_)
    {
    }
    bool operator < (const Foo & cmp) const
    {
        return num < cmp.num;
    }  
    int num;   
};

以後就能夠使用Foo做爲map的key了:html

map<Foo, int> dict;
dict[Foo(1)] = 1;

2)定義一個比較操做符,使用它做爲map的模板參數,代碼以下:

typedef std::pair<Foo, int> Foo2;
class Foo2Comparator
{
public:
    bool operator()(const Foo2& key1, const Foo2& key2) const
    {
        if (key1.first < key2.first)
        {
            return true;
        }
        else if (key2.first < key1.first)
        {
            return false;
        }
        else
        {
            return key1.second < key2.second;
        }
    }
};

這時候能夠使用Foo2做爲map的key了:less

map<Foo2, int, Foo2Comparator> dict2;
dict2[Foo2(Foo(1), 100)] = 1;

3)爲用戶自定義類型特化std::less,代碼以下:

namespace std
{
    template <>
    struct less<Foo2>
        : public binary_function <Foo2, Foo2, bool>
    {
        bool operator()(const Foo2& key1, const Foo2& key2) const
        {
            if (key1.first < key2.first)
            {
                return true;
            }
            else if (key2.first < key1.first)
            {
                return false;
            }
            else
            {
                return key1.second < key2.second;
            }
        }
    };
}

使用這種方法,聲明map時無需指定比較函數對象,由於默認的比較對象就是std::less<T>ide

map<Foo2, int> dict2;
dict2[Foo2(Foo(1), 100)] = 3;

2、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)即可獲得還不錯的哈希值(碰撞不會太頻繁),以下:spa

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);
	}
};

2)相等函數

        哈希須要處理碰撞,意味着必須得知道兩個自定義類型對象是否相等,因此必須得提供比較相等的方法,能夠 重載operator ==,能夠用 std::equal,也能夠實現一個 重寫 operator () 的類,這裏咱們採用後者,代碼以下:code

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

下面爲一個具體應用的例子:htm

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;
}

參考資料:對象

http://blog.sina.com.cn/s/blog_48d4cf2d0100mx4t.htmlblog

http://www.ithao123.cn/content-10629313.htmlthree

相關文章
相關標籤/搜索