起因是我在构思哈希表的结构,不想用链表处理冲突,那么就必须找一个伪随机函数,如果哈希值n对应的数组位置有值了,那么循环执行n=函数(n)
,直到n对应位置为空,函数必须足够“分散”,也就是每次调用结果“激烈跳动”,比如n=n+1
显然不合适,也必须是“伪”的,也就是同样的输入值,算出的结果必须一样。于是我查到了LCG算法,比如这里:https://www.cnblogs.com/vancasola/p/9951686.html,我构想的数组长度是2的整数倍,这样取余数用“与”操作很方便,然后写了一个简单的程序测试循环调用随机函数结果的分布:
#include <stdio.h>
#define len (1 << 6)
#define mask (len - 1)
int main() {
printf("%X %X\n", len, mask);
int arr[len] = {0};
int n = 1;
for (int i = 0; i < len; i++) {
arr[n]++;
n = (n * 5 + 1) & mask;
}
for (int i = 0; i < len; i++) {
printf("%d\t%d\n", i, arr[i]);
}
return 0;
}
然后我就发现了一个奇怪的现象,依文章里讲的那些取值根本不行,值都集中在几个位置,但是n*5+1
却非常神奇地完美覆盖了数组的每一个位置,也就是循环len次,数组每个位置都是完美的1,如果把循环次数减少,也会发现分布足够均匀,而且我测试了不同的2的次方的数组长度,发现没有例外。另外,+3
+5
+7
+11
都可以,好像是素数?我数学不好,这个现象能从数学上证明吗?