Hash 为什么不是';对于哈希表,哈希函数中的t模是否足够?

Hash 为什么不是';对于哈希表,哈希函数中的t模是否足够?,hash,hashtable,modulo,Hash,Hashtable,Modulo,我经常看到或听到模数被用作散列的最后一步或散列之后。e、 g.h(输入)%N其中h是散列函数,%是模运算符。如果我正在设计一个哈希表,并且想要将一组大的键映射到哈希表的一个较小的索引空间,那么模运算符不是实现了这一点吗?此外,如果我想随机化散列表中这些位置的分布,由模数生成的余数是否不够?哈希函数h在模运算符上提供了什么 我经常看到或听到模数被用作散列的最后一步或散列之后。e、 g.h(输入)%N其中h是散列函数,%是模运算符 的确如此 如果我正在设计一个哈希表,并且想要将一组大的键映射到哈希表

我经常看到或听到模数被用作散列的最后一步或散列之后。e、 g.
h(输入)%N
其中
h
是散列函数,
%
是模运算符。如果我正在设计一个哈希表,并且想要将一组大的键映射到哈希表的一个较小的索引空间,那么模运算符不是实现了这一点吗?此外,如果我想随机化散列表中这些位置的分布,由模数生成的余数是否不够?哈希函数
h
在模运算符上提供了什么

我经常看到或听到模数被用作散列的最后一步或散列之后。e、 g.
h(输入)%N
其中
h
是散列函数,
%
是模运算符

的确如此

如果我正在设计一个哈希表,并且想要将一组大的键映射到哈希表的一个较小的索引空间,那么模运算符不是实现了这一点吗

这正是模运算符的目的:限制数组索引的范围,所以是的

但您不能简单地单独使用模运算符:模运算符需要一个整数值:您不能获得“字符串在
N
上的模”或“对象图在
N
上的模”[1]

此外,如果我想随机化散列表中这些位置的分布,由模数生成的余数是否不够


不,它不会-因为模运算符不会给你伪随机输出-也不会有任何雪崩效应-这意味着相似的输入值会有相似的输出哈希,这将导致哈希表中的聚类,由于哈希冲突的可能性大大增加,这将导致低于标准的性能(因此需要较慢的技术,如线性探测,因为丢失了
O(1)
查找时间,因此无法达到哈希表的目的)

哈希函数
h
在模运算符上提供了什么

h
的域可以是任何内容,尤其是非整数值



[1] 从技术上讲,如果使用对象(即对象指针)的内存地址值,这是可能的,但如果您有不使用对象标识的哈希表键,例如堆栈分配的对象或自定义的
结构,则这不起作用。首先,哈希函数的主要目的是将非数字的内容转换为数字。即使您仅使用其后的模数来获取范围内的数字,获取数字仍然是非常困难的l第一步是散列函数的职责。如果你对整数进行散列,并且只使用整数作为自己的散列,那不是因为没有散列函数,而是因为你选择了标识函数作为散列函数。如果你不写出函数,那就意味着你内联了它


其次,散列函数可以提供更不可预测的分布,以减少意外冲突的可能性。人们处理的数据通常包含模式,如果您只是使用带模的简单标识函数,则输入中的模式可能使模更可能导致冲突。散列函数提供了一个打破这种局面的机会,因此模不太可能暴露原始数据序列中的模式。

“不,它不会——因为模运算符不会提供伪随机输出”。如果我们将整数作为输入(并对其执行模运算符),只要输入不与
number%N
中的
N
的倍数重叠,那么输出是否会不均匀分布?我完全理解您关于伪随机的观点,它有助于防止具有可能模式的不可预测的输入流引起冲突。但是,正确-在如果输入键类型是整数,则哈希函数可能是多余的,但是您需要确保您的键值域具有最佳数量的存储单元,否则您将有未使用的存储单元(例如,如果您被限制为ASCII
char
values
[a-Z]
那么您不需要超过26个存储箱——事实上,您也可以跳过使用哈希表,转而使用可直接索引的固定大小数组。