将一组整数从一个域中散列到一组存储桶中

时间:2018-07-06 10:00:59

标签: algorithm hash

说我有一组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)域,并从存储桶b的集合中输出1个存储桶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)的一种解决方案是仅创建一个这样的地图:

var map = {
  1: 2,
  5: 1,
  20: 5,
  50: 4,
  100: 3
}

但这是一种欺骗,因为JavaScript中的对象被实现为下面的哈希表(或类似的东西)。因此,我正在寻找一种从根本上讲如何做到这一点的方法,只是使用基本的汇编语言即可。

非常,我想这样做:

           1                     
    5      |                     
    |      |                    20
    |      |             50     |
    |      |      100    |      |
[ slot1, slot2, slot3, slot4, slot5 ]

1在某种程度上“散列”到大小为5的数组中的slot2(在此示例中该插槽是任意的),等等。

3 个答案:

答案 0 :(得分:1)

类似的事情应该起作用:

  1. 创建存储桶ID集合,并在散列之前填充它(假设这里的集合确保唯一性)。这意味着您必须提前知道要多少个桶。
  2. 对于输入集中的每个元素,计算hash(element) modulo bucketIds.size来查找下一个要使用的ID的索引。
  3. 从还原的ID集中删除生成的存储桶ID
  4. 重复(直到您完成操作或一组ID用尽为止)

Feel free to inspect the noddy implementation in JS using arrays(节点8)。

答案 1 :(得分:1)

假设整数值的域是从0到n-1的范围,并且您需要一组值[x 0 ,x 1 ,.. 。,x k-1 ]映射到从0到k-1的值。

创建一个n值的数组,其中包含从0到k-1的数字,它们的数量大致相等,例如[a 0 = 0,a 1 = 1, ...,a k = 0,...,a n = n%k]。

然后对于初始集合(x i ,其中i = 0 .. k-1)中的k个值中的每一个,将该数组的第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>

答案 2 :(得分:0)

如果您想要的功能不是直线图,则还可以尝试使用Polynomial Regression

下面是一个JavaScript示例,该示例在GNU许可下使用了free code

<template id="resultstemplate">
<option value="Alabama">AL-US</option>
<option value="California">CA-US</option>
<option value="Michigan">MI-US</option>
<option value="Texas">TX-US</option>
<option value="Wisconsin">WI-US</option>
</template>
<input type="text" name="search" id="search"  placeholder="type state name or code" list="searchresults" autocomplete="off" />
<datalist id="searchresults"></datalist>

<button id="myButton" type="button"
onclick="loadDoc('state_data.xml', myFunction)">Submit
</button>