【问题标题】:How do hash tables resolve bucket ambiguity and probes?哈希表如何解决桶歧义和探测?
【发布时间】:2024-01-23 17:51:01
【问题描述】:

我正在阅读 C 语言中的数据结构、算法和软件原理,试图深入了解数据结构的一些内部结构,有两件事让我非常困扰:

(1) 哈希表如何处理决定桶中的哪一项是您正在查找的项,如果它们都具有相同的哈希?

例如

  1. 获取键、值
  2. 在key上使用Hash算法找到索引尝试把值放入
  3. 如果slot被占用了,但是没有bucket(单入口),创建一个bucket,把当前item扔到bucket里面,然后把当前值扔进去。
  4. 现在我有一个包含一堆值的存储桶和一个“失物招领问题”,您无法分辨哪个值属于哪个键,因为所有键都映射到相同的散列并且存储桶中的项目没有key 键来搜索桶。

如果存储桶保存每个条目的键和值,这将起作用,但我很困惑,因为我找不到确认哈希表保存键及其条目的值的站点。

(2) 哈希表如何判断索引处的值是否是键的正确值,或者探测是否发现冲突并将其放在其他位置。

例如。

  1. 获取键、值
  2. 哈希键查找索引(0)
  3. 获取索引,使用简单的探测算法执行线性搜索,直到找到槽(槽 1 为空)。
  4. 现在我搜索我的键并找到索引 0。哈希如何知道索引 0 不是该键的正确项,但它已被探测到插槽 1?

同样,如果表保存了条目的键和值,这对我来说是有意义的,但我不确定哈希是否将键与条目的值一起保存,或者有另一种方法来确保项目位于哈希索引或桶索引是正确的项目,或者我误解了它。

为了澄清这个问题:哈希表是保存键和值以消除桶和探测序列的歧义,还是使用其他东西来避免哈希的歧义?

很抱歉这个粗略的问题,但我不得不问。

提前谢谢。

【问题讨论】:

  • “bucket中的item没有key可以通过key搜索bucket”——为什么你的hash表没有存储key?
  • @user2357112 我不确定是否有必要。我需要确认,我怀疑他们是否这样做。
  • @Dmitry:取决于用例。通常,存储条目。否则,冲突将需要返回给用户而不保存或覆盖之前的条目。

标签: algorithm hash disambiguation


【解决方案1】:

哈希表保存条目。条目由键和值组成。

如果哈希表都具有相同的哈希值,哈希表如何确定存储桶中的哪个项目是您要查找的项目?

因为查询是通过传递键来完成的。

散列的目的是减少查找索引的时间。他们的密钥被散列以找到正确的存储桶。然后,当项目从总 N 减少到非常小的 n 时,您甚至可以执行线性搜索以从具有相同哈希的所有键中找到正确的项目。

哈希表如何判断索引处的值是否是键的正确值,或者探测是否发现冲突并将其放在其他地方。

同样,这是因为哈希表会保存条目而不仅仅是值。如果在发生冲突的情况下,哈希表发现在这个桶中找到的键不是被查询的键,则哈希表知道冲突发生得更早,并且该键可能在下一个桶中。请注意,在这种情况下,存储桶存储单个条目,这与第一个答案的情况不同,存储桶可能存储 LinkedList 或条目树。

【讨论】:

  • 好吧,这是有道理的。我很难相信哈希条目存储键和值,因为我总是将哈希表视为从键到值的一种方式映射,而不是键到由键和值组成的条目。假设没有尝试在同一个键下存储多个不同的值,则拥有一个键可以保证所有条目都可以映射回该键,这很容易检测并忽略此类插入请求并报告该尝试。感谢您确认确实需要将密钥存储在哈希表条目中,除非存在损坏哈希表的情况。
  • @Dmitry:不仅密钥也被存储,密钥应该永远在插入条目后被修改,因为现在这个带有修改密钥的条目不是正确的存储桶因此在搜索时无法再次找到它。
  • 是否可以重新映射键,只要您使用生成此类键的哈希算法创建一个全新的哈希表,并通过新算法传递所有条目的键以找到新值,从而维护哈希表不变量?有趣的是,如果不知道哈希表条目中的键,这也是不可能的。
  • @Dmitry:只要你重新散列并将条目添加到正确的索引中,你就可以为所欲为。