从链式哈希表中有效地挑选一个随机元素?

Posted

技术标签:

【中文标题】从链式哈希表中有效地挑选一个随机元素?【英文标题】:Efficiently picking a random element from a chained hash table? 【发布时间】:2012-01-27 14:29:48 【问题描述】:

只是为了练习(而不是作为家庭作业)我一直在尝试解决这个问题(CLRS,第 3 版,练习 11.2-6):

假设我们在大小为 m 的哈希表中存储了 n 个键,其中 通过链接解决冲突,并且我们知道每个冲突的长度 链,包括最长链的长度 L。描述一个 从密钥中随机均匀地选择一个密钥的过程 在哈希表中并在预期时间 O(L * (1 + m/n)) 内返回它。

到目前为止,我认为每个键被返回的概率是 1/n。如果我们尝试获取一个介于 1 到 n 之间的随机值 x,并尝试先按桶排序,然后沿着桶中的链依次找到第 x 个键,则需要 O(m) 才能找到正确的桶通过桶一个接一个和 O(L) 时间来获得链中的正确密钥。

【问题讨论】:

最坏的情况是 O(mn) 用于查找相关项目,但每个项目的预期时间(如问题所述)为 O(1+m/n) 并且将为 O(L*(m /n+1)) 对于所有这些。 长度信息是如何存储的?我在想,如果一个桶包含所有元素而其余元素为零,那么您甚至找不到比 O(n) 时间快的桶。还有其他关于元素位置的信息吗? 【参考方案1】:

重复以下步骤,直到返回一个元素:

随机选择一个桶。设k 为桶中元素的数量。 从1 ... L中均匀随机选择p。如果是p <= k,则返回桶中的pth 元素。

应该清楚,该过程均匀地随机返回一个元素。我们有点将拒绝采样应用于放置在二维数组中的元素。

每个桶的预期元素数量为n / m。采样尝试成功的概率为(n / m) / L。因此,查找存储桶所需的预期尝试次数为L * m / n。加上从桶中检索元素的O(L) 成本,预计运行时间为O(L * (1 + m / n))

【讨论】:

+1 对 1 到 L 范围内采样的出色洞察力。完成矩形并向其投掷飞镖的几何直觉可能有助于使解释更清晰。 "每个桶的预期元素数是 n / m",没有假设在问题中说它的简单统一哈希,它只是说"我们知道每个链的长度,包括最长链的长度 L"。

以上是关于从链式哈希表中有效地挑选一个随机元素?的主要内容,如果未能解决你的问题,请参考以下文章

链式与开放式寻址的哈希表中的缓存性能

开地址哈希表(Hash Table)的原理描述与冲突解决

从哈希表中删除条目的最佳方法

在通用哈希表中查找项目?

随笔64 hash表

hash_set和hash_map