【发布时间】:2014-06-27 05:02:41
【问题描述】:
据我所知,散列函数的目的是尽可能均匀地分配数据,当您遇到冲突时,您有多种选择:
- 寻找下一个空槽
- 生成不同的哈希并尝试将其粘贴到其他地方
- 将其放入溢出容器(可以是列表、另一个哈希表或其他)
- 将其放入下一个空闲桶槽中
最后一个困扰着我,因为如果你要为每个地址制作一个带有 2 个插槽的哈希表,为什么不制作一个两倍大的哈希表呢?那是除非桶是动态分配的。在我的情况下,表的数据位于磁盘上,这意味着另一个磁盘访问+管理可变长度数据。在我看来,虽然水桶仍然是最受青睐的选择,但这是为什么呢?我错过了什么?
【问题讨论】:
-
“在我看来,桶仍然是最受青睐的选择”为什么?第一个选项称为线性散列,在大多数情况下是最简单的(有点令人惊讶)仍然是最有效的。
-
“1.寻找下一个空槽”与“4.将其放入下一个空闲桶槽”有何不同?您习惯的术语是每个桶有固定数量的“插槽”吗?他们说“每个 address 有 2 个插槽” - 你是指每个存储桶吗? “桶是动态分配的”-您是否再次引用“3”。 - 因为动态存储桶对我来说听起来像是列表/向量。
-
无论如何,对于磁盘表,加载磁盘区域的成本很高,因此最好使用任何空闲的存储桶,而不是求助于查看另一个磁盘区域。我不建议每个桶使用多个“插槽” - 只需尝试另一个桶。一个好主意是使用跳过多个存储桶的“置换列表”(可能在已加载的磁盘区域内包装几次重试,然后进行蛮力搜索,然后移动到另一个磁盘区域或重新散列)。置换列表应避免总和重复的运行:例如1 3 6 没问题 (3-1 != 6-3, n*(3-1) != 6-1), 11 不好: 6-1 == 11-6, 13 ok....
-
@TonyD 第一条评论:它有所不同,因为在 #4 中,您将为每个哈希的 kvps 预分配多个空间。是的是的。不,我的意思是桶对我有意义的唯一方法是,如果它们被动态分配以节省内存,是的。第二条评论:是的,这几乎结束了#2。是的,这听起来是个好主意。
-
@KarliRaudsepp:每个散列值多个预分配空间的想法没有用......考虑到额外的内存使用,你最好让散列在所有可用内存上展开,这样有开始时减少碰撞,然后使用讨论的任何链接/重新散列/置换列表技术处理碰撞。