有哪些算法可用于调整哈希表的大小?

Posted

技术标签:

【中文标题】有哪些算法可用于调整哈希表的大小?【英文标题】:What algorithms are available to resize a hash table? 【发布时间】:2011-01-13 02:29:30 【问题描述】:

我已经在 C 中实现了自己的哈希表函数,但目前它不支持调整大小。我想知道除了创建一个新的空哈希表并将所有内容移到那里的蛮力方式之外,还存在哪些算法?

【问题讨论】:

【参考方案1】:

有增量调整大小。

来自***:

增量调整大小

一些哈希表的实现, 特别是在实时系统中,不能 付出扩大哈希的代价 一次全部使用表,因为它可能 中断时间关键的操作。如果 无法避免动态调整大小, 解决方案是执行调整大小 逐渐:

在调整大小期间,分配新的 哈希表,但保留旧表 不变。 在每个查找或删除操作中,检查两个表。 仅在新表中执行插入操作。 在每次插入时,还将 r 个元素从旧表移动到新表 桌子。 当从旧表中删除所有元素时,将其释放。

为了确保旧表将 在新之前完全复制过来 表本身需要放大,它 有必要增加 表格至少乘以 (r + 1)/r 在调整大小时。

所以这不是将所有元素从旧表移动到新表中的聪明方法(如果有的话,我还没有看到);相反,它通过允许逐步进行迁移来减轻调整大小的负担。

【讨论】:

【参考方案2】:

***有一些关于这个主题的words of wisdom。

另外,它不是一个解决方案,但可能是其中的一部分 - 如果您在 Windows 下,您可能会使用 VirtualAlloc 系列函数,它允许您在不实际提交内存页面的情况下保留地址空间。也就是说,用外行的话来说,你会做类似“malloc”的事情,并告诉它“保留 1000MB,但只让前 10 个可用”。因此,如果您写入超过 10MB,您会遇到通常的崩溃。但是到了扩展的时候,你只需说“好的,在第一个之后再给我 10MB”。下一个 10MB 在前 10MB 之后的地址处可用。这就像调整数组的大小。实际使用的 RAM 将只是您需要的数量,但内存地址将提前保留,以便其他内存分配操作不会使用它们。

【讨论】:

这是调整数组大小的一种非常聪明的方法——如果你有地址空间要刻录(x64)——但它不适用于哈希表,你仍然需要重新散列所有内容(它是更复杂的做法。) @Eloff - 好吧,正如我所说 - 它本身不是解决方案,只是解决方案的一部分。而且您不必保留那么多的地址空间。只是一些合理的数量。这不是灵丹妙药,它只是让调整大小的操作更快。 我知道你现在用这个去哪里了,但它实际上会使调整大小更快令人怀疑。这里的主要开销不是内存分配,这几乎没有功能。所有时间都进入软页面错误以将新内存带入进程地址空间(通常发生在内存分配器中,当它将内存归零时)以及重新散列和重新插入哈希表中的所有元素所需的成本.但是对于动态数组,您不需要复制任何内容,并且您可以一次支付一个软页面错误(一次增长一页),这非常棒! 我可能会因为小故障而出去吃午饭,不确定。但不管提交和归零内存的成本是分配它的成本的主要部分。 @Eloff - 也许吧。但如果是这样,那么我很难看到虚拟内存分配器的这一特性的任何其他可能的应用程序。【参考方案3】:

通常的解决办法是让客户端代码预先猜测最佳桶数。这是有用的,客户通常会合理猜测表格中有多少元素。如果您想自动执行此操作,则首先必须为存储桶大小声明一个素数数组。当您看到存储桶的负载因子过高时,请选择数组中的下一个素数,重新创建存储桶列表并将元素从旧存储桶移到新表中。

【讨论】:

以上是关于有哪些算法可用于调整哈希表的大小?的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法--------哈希表

哈希表与哈希(Hash)算法

哈希表、哈希算法、一致性哈希表

哈希算法下——哈希算法在分布式系统中有哪些应用?

[算法导论]#1 摊还分析

哈希表的静态,动态,以及key/value形式