需要帮助开始构建我自己的哈希表

Need help starting to build my own hash table

本文关键字:我自己 自己的 哈希表 构建 开始 帮助      更新时间:2023-10-16

我正在学习哈希表,试图了解它们是如何工作的。我想制作一个相当简单的具有单独链接的哈希表(使用数组中的列表)。我有几个问题:

  1. 假设密钥可以是任何类型,我会要求用户实现哈希函数,对吧?这能避免吗?

  2. 用户还需要在初始化时提供包含列表(用于冲突)的数组的长度,对吗?这能避免吗?

如果你有任何其他提示,或者可能有一些清晰的C++哈希表代码示例,我将不胜感激。

谢谢你的帮助。

通常,是的,您需要客户端指定哈希函数,因为如果您正在编写一个通用哈希表并在任意类型T上操作,则不知道如何以语义上有意义的方式对其进行哈希。您可以通过对要存储的元素类型和哈希函数的类进行参数化来实现这一点。例如:

template <typename T, typename Hash = std::hash<T>>
    class MyHashTable {
    /* ... */
}

在这里,您可以使用模板中的默认参数来选择默认的散列函数,除非用户另有指定。

虽然客户端通常可以指定表的初始大小,但这不是必需的。你可以对bucket的数量进行有根据的猜测(比如说,最初使用17个bucket),随着负载因子的增加,表会增加。例如,这与std::vector的工作方式类似:实现可以选择默认大小,但如果客户端明确要求预大小的向量或调用reserve,则实现会从用户那里获得提示。例如,您可以有一个形式的构造函数

template <typename T, typename Hash = std::hash<T>>
    class MyHashTable {
public:
    MyHashTable(unsigned numBuckets = 17);
}

这样,客户端可以只构建一个具有默认桶数的哈希表,或者如果他们知道自己想要的桶数,可以将其指定为参数。然而,您可能还想将bucket作为一个细节隐藏起来,只需让客户端指定他们希望放入表中的元素数量,然后让您的类在幕后为此进行计算。这使得在幕后切换实现变得更容易,因此,如果您想使用动态完美哈希表之类的东西来代替链式哈希,则类可以处理计算初始大小的复杂性。

至于代码示例,我不知道如何在不透露构建哈希表所涉及的大量复杂性的情况下提供任何代码示例。:-)如果有一段特定的代码你感兴趣,并且在自己编写时遇到困难,可以将其作为一个单独的问题发布,这样你就可以获得更有针对性的反馈。

希望这能有所帮助!

查看哈希算法的各种实现。有很多可用的。如果您愿意,可以将哈希存储设为可变存储。这取决于你。对于大多数哈希算法,冲突是可能的。记住这一点。

如果你想了解哈希表,我建议你从最简单的哈希表开始,即线性链接哈希表

在这里,您考虑一个固定大小的指针数组(指向您定义的类型项目的指针),其中存储您的项目,还考虑有一些计数器,一个用于跟踪数组的长度,另一个用于记录添加到表中的项目数,直到某个时刻

您可以使用宏来定义向哈希表中添加项的功能,如

 h(k) = k % M  

其中k是要添加的项的索引(键),M是表示指针数组大小的素数(例如13、29、41、543),h(k)将给出要插入项的位置。

你应该考虑使用固定大小的指针数组的原因是因为这样你就有了

 O(n) 

成本。

因此,从这个简单的函数开始,你可以修改它,并考虑实现一些更复杂的函数,如开放地址、线性探测、二次探测和双散列

至于用户要求的关于项目数量的输入,我完全同意templatepedef早些时候所说的