Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.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
Hash 函数_Hash_Hashtable_Perfect Hash - Fatal编程技术网

Hash 函数

Hash 函数,hash,hashtable,perfect-hash,Hash,Hashtable,Perfect Hash,我正在尝试散列这些值 10, 100, 32, 45, 58, 126, 3, 29, 200, 400, 0 我需要一个函数,将它们映射到一个大小为13的数组,而不会引起任何冲突 我花了好几个小时仔细考虑这个问题,在谷歌上搜索,但我还是弄不明白。我还没有找到可行的解决办法 我怎样才能找到这种散列函数呢?我玩过gperf,但我不太懂它,也无法得到我想要的结果。如果你知道确切的键,那么生成一个完美的哈希函数就很简单了- int hash (int n) { switch (n) {

我正在尝试散列这些值

10, 100, 32, 45, 58, 126, 3, 29, 200, 400, 0
我需要一个函数,将它们映射到一个大小为13的数组,而不会引起任何冲突

我花了好几个小时仔细考虑这个问题,在谷歌上搜索,但我还是弄不明白。我还没有找到可行的解决办法


我怎样才能找到这种散列函数呢?我玩过gperf,但我不太懂它,也无法得到我想要的结果。

如果你知道确切的键,那么生成一个完美的哈希函数就很简单了-

int hash (int n) {
  switch (n) {
    case 10:   return 0;
    case 100:  return 1;
    case 32:   return 2;
    // ...
    default:   return -1;
  }
}
找到一个 我尝试了一些方法,发现其中一种是半手动的:

(n ^ 28) % 13
半手动部分是以下ruby脚本,我使用该脚本使用一系列参数测试候选函数:

t = [10, 100, 32, 45, 58, 126, 3, 29, 200, 400, 0]
(1..200).each do |i|
  t2 = t.map { |e| (e ^ i) % 13 }
  puts i if t2.uniq.length == t.length
end

我做了一个快速检查,使用SHA256散列函数,然后在Mathematica中进行13的模除运算。对于C++,这个函数应该在OpenSSL库中。看这个


如果你做了大量的散列和查找,模块化除法是一个非常昂贵的重复操作。还有另一种将n位哈希函数映射到i位索引的方法。请参阅Michael Mitzenmacher的这篇文章,了解如何在C中使用位移位操作。希望这会有所帮助。

Bob Jenkins也有一个这样的程序:


除非你非常幸运,否则对于给定的数据集没有“好”的完美哈希函数。完美的散列算法通常在键上使用一个简单的散列函数(使用足够的位以避免冲突),然后使用一个表来完成它。

只是一些准分析性的散列:

在你的一组数字中,总共11个,3个是奇数,8个是偶数。 查看最简单的散列形式-%13-将为您提供以下散列值: 10 - 3, 100 - 9, 32 - 6, 45 - 6, 58 - 6, 126 - 9, 3 - 3, 29 - 3, 200 - 5, 400 - 10, 0-0

当然,由于碰撞的数量,这是不可用的。需要更详细的东西

为什么说这是显而易见的? 考虑到数字太少,任何精心设计的——或者更确切地说,“不那么简单”——算法都可能比switch语句或(我更喜欢)简单地搜索大小为11个位置的无符号短/长向量并使用匹配的索引慢

为什么要使用向量搜索

  • 通过将最常出现的值放置在向量的开头,可以对其进行微调
  • 我假设其目的是将散列索引插入到具有良好顺序编号的开关中。在这种情况下,首先使用开关查找索引,然后将其插入另一个开关似乎是浪费。也许你应该考虑不使用散列,直接进入最终开关?
  • 哈希的开关版本无法微调,并且由于值的差异很大,将导致编译器生成一个二元搜索树,这将导致大量比较和条件/其他跳转(特别昂贵),这需要时间(我假设您已经转向哈希的速度)并需要空间
  • 如果您想进一步加快矢量搜索速度,并且使用x86系统,则可以基于汇编指令repne scasw(short)/repne scasd(long)实现矢量搜索,这将快得多。在几条指令的设置时间之后,您将在一条指令中找到第一个条目,在十一条指令中找到最后一条,然后是几条指令。这意味着5-10条指令是最佳情况,15-20条指令是最差情况。除了一两种情况外,这应该在所有情况下都优于基于开关的哈希
  • 在某些平台(例如嵌入式平台)上,模运算成本很高,因此最好避免使用
    %13
    。但是低阶位的
    运算成本较低,相当于二次幂的模

    我尝试编写一个简单的程序(用Python)来搜索11个数据点的完美散列,使用诸如
    ((x shift_值)之类的简单形式
    def find_hash():
    def hashf(val,i,j=None,k=None):
    返回(右移(val,i)^右移(val,j)^右移(val,k))&0xF
    对于X范围内的i(-7,8):
    对于x范围内的j(i,8):
    #对于x范围内的k(j,8):
    #j=无
    k=无
    输出=设置()
    对于数据中的val:
    hash_val=hashf(val,i,j,k)
    如果哈希值>=13:
    通过
    #中断
    如果输出中存在哈希值:
    打破
    其他:
    输出。添加(哈希值)
    其他:
    打印i、j、k、输出
    如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
    find_hash()
    
    尝试以下方法,将n值映射到0到12之间的唯一索引
    (1369%(n+1))% 13 < /p>对不起,我把它编辑成C++,然后C++标签从问题中删除。如果你想,你可以回复。ME,它应该是C类伪代码,现在更好了,Tythe是一个有效的表搜索。哈希函数的好处之一是:它允许比表搜索更快地评估命中/误。@克雷格明显比表格搜索快,即使使用
    gcc-O0
    这也比我的机器上的简单线性表格搜索快5倍,使用
    -O2
    线性搜索需要一秒钟,
    time
    报告100万次查找的总时间
    0.00
    ,速度几乎与公认的答案相同使用
    -O0
    的迭代次数超过1亿次,使用
    -O2
    的迭代次数在0.2s以内。如果您只需要计算出密钥是否存在/有效-
    哈希(n),则此哈希函数会更快==-1
    不需要内存访问…您可以安全地添加键,同时函数保持完美。您的哈希可能比数据表查找更快,但这不是我的意思。澄清一下:您的哈希可能适用于这个小数据集,同意。B
    #define HASH(x)    ((((x) << 2) ^ ((x) >> 2)) & 0xF)
    
    data = [ 10, 100, 32, 45, 58, 126, 3, 29, 200, 400, 0 ]
    
    def shift_right(value, shift_value):
        """Shift right that allows for negative values, which shift left
        (Python shift operator doesn't allow negative shift values)"""
        if shift_value == None:
            return 0
        if shift_value < 0:
            return value << (-shift_value)
        else:
            return value >> shift_value
    
    def find_hash():
        def hashf(val, i, j = None, k = None):
            return (shift_right(val, i) ^ shift_right(val, j) ^ shift_right(val, k)) & 0xF
    
        for i in xrange(-7, 8):
            for j in xrange(i, 8):
                #for k in xrange(j, 8):
                    #j = None
                    k = None
                    outputs = set()
                    for val in data:
                        hash_val = hashf(val, i, j, k)
                        if hash_val >= 13:
                            pass
                            #break
                        if hash_val in outputs:
                            break
                        else:
                            outputs.add(hash_val)
                    else:
                        print i, j, k, outputs
    
    if __name__ == '__main__':
        find_hash()