【发布时间】:2014-03-25 22:48:19
【问题描述】:
我正在阅读 Robert Sedwick 的 C++ 算法散列
此字符串键的哈希函数实现涉及键中每个字符的一次乘法和一次加法。如果我们将常数 127 替换为 128,则程序将使用 Horner 方法简单地计算与密钥的 7 位 ASCII 表示对应的数字除以表大小时的余数。如果表大小是 2 的幂或 2 的倍数,则以 127 为基数有助于我们避免异常。
int hash(char *v, int M)
{ int h = 0, a = 127;
for (; *v != 0; v++)
h = (a*h + *v) % M;
return h;
}
理论上理想的通用散列函数是一个大小为 M 的表中两个不同键之间发生冲突的机会恰好是 1/M。可以证明,对程序 14.1 中的系数 a 使用一系列不同的随机值,而不是固定的任意值,将模块化散列转换为通用散列函数。但是,为密钥中的每个字符生成一个新的随机数的成本可能会令人望而却步。程序 14.2 演示了一个实际的折衷方案:我们通过生成一个简单的伪随机序列来改变系数。
总之,要将散列用于抽象符号表实现,第一步是扩展抽象类型接口以包含散列操作,该操作将键映射为小于表大小 M 的非负整数。直接实现
inline int hash(Key v, int M) { return (int) M*(v-s)/; }
为值 s 和 t 之间的浮点键做这项工作;对于整数键,我们可以简单地返回 v % M。如果 M 不是素数,哈希函数可能会返回
(int) (.616161 * (float) v) % M
或类似整数计算的结果,例如
(16161 * (unsigned) v) % M.
如果表大小是 2 的幂或 2 的倍数,我的问题是作者如何表示素数基数 127 有助于我们避免异常?
authorm 所说的“对于整数键,我们可以简单地返回 v % M”是什么意思?
作者所说的“如果 M 不是素数,哈希函数可能会返回”是什么意思
(int) (.616161 * (float) v) % M
或类似整数计算的结果,例如
(16161 * (无符号) v) % M.
作者是如何想到 .616161 和 16161 的?
请求帮助以通过简单示例理解
【问题讨论】: