使用HashTable实现HashMap

Implementing a HashMap using a HashTable implementation

本文关键字:HashMap 实现 HashTable 使用      更新时间:2023-10-16

我有一个包含insert, remove, find, exists等函数的哈希表实现。

使用这个哈希表,我想实现一个hashmap。

所以我想创建一个简单的pair类,它只包含一个键和一个值。它会使operator=过载,只考虑键的相等性。此外,哈希函数将获得一个pair对象作为输入,并返回哈希值,同样只考虑密钥部分。

因此,我将在哈希映射中有一个hashtable<pair>,它本质上类似于hashtable<key>,因为它只考虑关键部分,只携带一个值成员。

但是问题出现了。

例如,我想实现一个exists函数,该函数将检查hashmap中是否存在具有指定键的pair。它会取一个键并检查这个键是否在地图中。这将使用散列表的exists来实现。但是hashtable::exists现在接受一对类型作为输入。

所以现在我有了这些我不太喜欢的选择

  • 用key创建pair对象,不初始化value部分

  • 将键对象强制转换为对对象(如reinterpret_cast(&key)),因为在这种情况下哈希表的函数将只使用对中的键部分。

第一个创建了一个不必要的副本。第二个键的地址可能不等于pair的对象地址。虽然我相信我可以确定知道密钥的地址考虑到我可以计算

(&pair.key) - (&pair)

使用它,我可以进行适当的强制类型转换,将密钥作为一对传递。

有什么替代方案吗?

如果您查看像google::dense_hash_map这样的散列映射的现有实现(我将此作为示例,因为我认为它比std::unordered_map这样的STL代码更容易阅读),您将看到散列映射不仅仅是一个模板化的散列表。

换句话说,它不是这样实现的:

template <class T>
struct hash_table { ... };
template <class Key, class Value>
using hash_map = hash_table<std::pair<Key, Value>>;

…但就像:

template <class Value, class Key> 
struct hash_table { ... };
template <class Key, class Value> 
struct hash_map
{
    using ht = hash_table<std::pair<Key, Value>, Key>;
    ht _ht;
};

然后,在hash_table<Value, Key>中,你可以有insert(const Value&),也可以有find(const Key&),因为这个类知道所有的类型。

最重要的是你可以很容易地实现hash_set。整个逻辑将在您的hash_table类中,hash_maphash_set仅转发调用并为API的客户端做一些修饰性的东西。