C++ map和unordered_map自定义key

一、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了:

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了:

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>

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

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

2)相等函数

        哈希需要处理碰撞,意味着必须得知道两个自定义类型对象是否相等,所以必须得提供比较相等的方法,可以 重载operator ==,可以用 std::equal,也可以实现一个 重写 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;
	}
};

下面为一个具体应用的例子:

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.html

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

转载于:https://my.oschina.net/shou1156226/blog/757568

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值