假设我有一组介于 1-100 之间的整数。我只会从帽子里抽出 5 个这样的整数。然后我想将这 5 个整数放入保证唯一的 5 个桶中(无需重复数据删除或使用类似 quadratic probing 的任何东西)。想知道如何做到这一点。
例如,假设我有这些数字(从 1 到 100 随机):
1 5 20 50 100
然后我想将这些数字放入这 5 个桶中:
a b c d e
使用一些散列函数来完成它。例如,也许像这样:
hash(1) -> b
hash(5) -> a
hash(20) -> e
hash(50) -> d
hash(100) -> c
想知道如何编写散列函数以使其接受一个数字 x
来自数字的域 D
和一组数字 D(X)
来自该域,并输出 1 个桶 b
来自一组桶 B
.
H : D(X) -> B
下次我可能会有 1 到 1,000 之间的 6 个数字,分为 6 个桶。那么我需要一个新的哈希函数,它使用这些约束(6 个数字,6 个桶,范围 1-1,000)。
目标是尽可能少的步骤。
注意:这个例子的哈希函数不会在大于 10,000 的域中取整数,而且整数集的大小也限制在一些小数字,比如 1,000。
更新
基本上我正在努力实现这一目标:
// var domain = [1, 2, ..., 100]
// var set = [1, 5, 20, 50, 100]
// var buckets = [1, 2, 3, 4, 5]
hash(1) // 2
hash(5) // 1
hash(20) // 5
hash(50) // 4
hash(100) // 3
function hash(integer) {
if (integer == 1) return 2
if (integer == 5) return 1
if (integer == 20) return 5
if (integer == 50) return 4
if (integer == 100) return 3
}
但我不知道如何动态构造哈希函数。
一个解决方案(在 JavaScript 中)是像这样创建一个 map :
var map = {
1: 2,
5: 1,
20: 5,
50: 4,
100: 3
}
但这有点作弊,因为 JavaScript 中的对象是作为下面的哈希表(或类似的东西)实现的。所以我正在寻找如何在低层次上做到这一点,基本上只是使用汇编给你的东西。
差不多,我想这样做:
1
5 |
| | 20
| | 50 |
| | 100 | |
[ slot1, slot2, slot3, slot4, slot5 ]
在哪里1
以某种方式“散列”进入那个slot2
在一个大小为 5 的数组中(对于这个示例,该插槽是任意的),等等。
最佳答案
假设您的整数值的域是从 0 到 n-1 的范围,并且您想要一组值 [x0, x1, .. ., xk-1] 映射到从 0 到 k-1 的值。
创建一个包含 n 个值的数组,其中包含大致相等数量的从 0 到 k-1 的数字,例如 [a0 = 0, a1 = 1, ..., ak = 0, ..., an = n%k].
然后对于初始集合中的每个 k 个值(xi,其中 i = 0 .. k-1),将此数组的第 k 个元素更改为 i,或者通过直接分配或通过与来自其他地方的值交换(注意不要破坏初始集合的前一个元素的值集)。
然后要对值 y 进行哈希处理,只需从该数组中获取第 y 个值即可。
演示
这是一个基本实现上述算法的 Javascript 演示,除了它不是用 0 到 k-1 的值预填充数组,它首先插入所选项目的哈希值,然后用从 0 到 k-1 的重复数字序列。通过使用随机序列而不是递增值,您可能会获得更好的抗碰撞性,但我希望您明白了。
var hash_array;
function generate_hash() {
var i, j, k;
var v = document.getElementById;
var n = document.getElementById("n").value;
// Create a new hash lookup table
hash_array = Array(n);
// Initialize every value to -1
for (i=0; i<n; i++) hash_array[i] = -1;
// Map the given values to the first k hash buckets
var initial_values = document.getElementById("init").value.split(/ +/);
k = initial_values.length;
for (i=0; i<k; i++) {
hash_array[initial_values[i]] = i;
}
// Fill the remaining buckets with values from 0 to k-1
// This could be done by selecting values randomly, but
// here we're just cycling through the values from 0 to k-1
for (i=j=0; i<hash_array.length; i++) {
if (hash_array[i] == -1) {
hash_array[i] = j;
j = (j + 1) % k;
}
}
document.getElementById("gen").innerHTML = "Hash lookup table:<br>" + hash_array.join(", ");
}
<h2>Demo</h2>
<p>Creating a hash function that works on integer values less than <i>n</i>. What is the value of <i>n</i>?<br>
<input type="number" id="n" min="6" max="100" value="20"/></p>
<p>Enter a few different values separated by spaces. These will hash to the first buckets<br/>
<input type="text" size="40" id="init" value="2 3 5 6 9"/></p>
<p id="gen"><button onclick="generate_hash(); return false">Generate hash table</button></p>
关于algorithm - 将域中的一组整数散列到一组桶中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51207863/