Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 散列函数分布在n个值上(带扭曲)_Algorithm_Hash - Fatal编程技术网

Algorithm 散列函数分布在n个值上(带扭曲)

Algorithm 散列函数分布在n个值上(带扭曲),algorithm,hash,Algorithm,Hash,我想知道是否有任何散列函数可以将输入分布到n个值上。当然,分布应该相当均匀。但有一个转折点。对于n的小变化,很少有元素会得到新的散列。最佳情况下,它应该在n个值上均匀地分割所有k,如果n增加到n+1,则只有k/n-k/(n+1)值必须移动到新哈希中均匀分布。很明显,有一个简单地创建统一值然后修改的散列可以工作,但是这会移动大量散列来填充新节点。这里的目标是尽可能少的值落在一个新的存储桶中。假设2^{n-1}

我想知道是否有任何散列函数可以将输入分布到n个值上。当然,分布应该相当均匀。但有一个转折点。对于n的小变化,很少有元素会得到新的散列。最佳情况下,它应该在n个值上均匀地分割所有k,如果n增加到n+1,则只有k/n-k/(n+1)值必须移动到新哈希中均匀分布。很明显,有一个简单地创建统一值然后修改的散列可以工作,但是这会移动大量散列来填充新节点。这里的目标是尽可能少的值落在一个新的存储桶中。

假设2^{n-1} 这很容易做到:

只需像平常一样为每个键生成一个散列值。然后,将密钥k分配给[0,N]中的节点:

因此,当您添加节点1时,它会从节点0窃取一半的项目。 添加节点2时,它会从前2个节点中窃取1/3的项目。 等等


编辑:添加了mix()函数,以对每个n的散列进行不同的混合,否则当n不是素数时会出现不一致性。

Hmm,我在实现这一点时遇到了一些困难。假设n是10,这使得n4(2^3=8<10<2^4=16)。然后我计算H(v),在本例中,Pythons内置哈希函数,返回64位哈希。我只保留前4位(请记住,这会使一些负数变为正数)。但是堆栈崩溃,因为H(v)的哈希不一定比v的哈希小。您是否考虑了某个H?进行了更多测试,并在移动H(v)后每次运行时(再次将一些负数变为正数)它似乎都会起作用。我认为这可能与Python如何进行散列和负数有关(必须做一个变通方法,以实际获得n个前位,而不是让数字变为负数)做了更多的测试,您的第三个属性似乎是错误的。在我的测试中,1000个条目从16个节点到17个节点,最终有945个更改。从32个节点到33个节点,我做了973个更改。因此,它似乎实际上更接近所有数据,必须重新验证。@PMunch我认为您一定误解了一些非常严重的内容。您不应该这样做我不确定你关于“将一些否定变为积极”的评论是什么意思,但我们应该在这里谈论未签名的数字——没有否定。@PMunch啊,我打赌这里的罪魁祸首是Python的(有点漂亮)为整数选择哈希函数:即标识函数。基本上使用任何其他哈希函数,效果会更好;例如,
hash(str(x))
。Python不是我最擅长的语言,但请耐心等待,我很快会发布一些代码并进行一些分析。
import math

def ilog2(m): return int(math.ceil(math.log(m,2)))

def hash_into(obj, N):
    cur_hash = hash(obj)
    mask = pow(2, ilog2(N)) - 1
    while (cur_hash & mask) >= N:
        # seems Python uses the identity for its hash on integers, which
        # doesn't iterate well; let's use literally any other hash at all
        cur_hash = hash(str(cur_hash))
    return cur_hash & mask

def same_hash(obj, N, N2):
    return hash_into(obj, N) == hash_into(obj, N2)

def bump_stat(objs, N):
    return len([obj for obj in objs if same_hash(obj, N, N+1)])

alphabet = [chr(x) for x in range(ord('a'),ord('z')+1)]
ascending = alphabet + [c1 + c2 for c1 in alphabet for c2 in alphabet]

def main():
    print len(ascending)
    print bump_stat(ascending, 10)
    print float(bump_stat(ascending, 16))/len(ascending)
# prints:
# 702
# 639
# 0.555555555556
Let H(k) be the hash of k.

int hash = H(k);
for (int n=N-1;n>0;--n) {
   if ((mix(hash,n) % (i+1))==0) {
      break;
   }
}

//put it in node n