【问题标题】:How does the hash part in hash maps work?哈希映射中的哈希部分如何工作?
【发布时间】:2011-02-07 21:36:12
【问题描述】:

所以在维基百科的hash maps article 中有这张漂亮的图片:

到目前为止一切都清楚了,除了中间的哈希函数

  • 函数如何从任何字符串生成正确的索引?索引实际上也是整数吗?如果是,函数如何输出1John Smith2Lisa Smith 等?

【问题讨论】:

    标签: hash hashmap


    【解决方案1】:

    这是哈希图/字典等的关键问题之一。你必须选择一个好的散列函数。一个非常糟糕但快速的哈希函数可能是键的长度。您会立即看到,您会遇到很多冲突(不同的键,但相同的哈希)。另一个不好的哈希函数可能是密钥第一个字符的 ASCII 值。也有很多碰撞。
    所以你需要一个比这两个更好的功能。例如,您可以添加(异或)关键字符的所有 ASCII 值并混合长度。在实践中,您通常依赖于要散列的对象的值(字段)(相同的值给出相同的散列 => 值类型)。例如,对于引用类型,您可以混合在内存位置中。

    在您的示例中,这只是简化了很多。没有真正的哈希函数会将这些键映射到序列号。

    也许你想读一读我的previous answers to hashmaps

    【讨论】:

      【解决方案2】:

      一个简单的哈希函数可能如下:

      $hash = $string[0] % HASH_TABLE_SIZE;
      

      此函数将返回一个介于 0 和 HASH_TABLE_SIZE - 1 之间的数字,具体取决于字符串的第一个字母。这个数字可以用来在哈希表中找到正确的位置。

      一个真正的哈希函数会考虑一个字符串中的所有字母,它会被设计成在桶之间有一个均匀的分布。

      【讨论】:

        【解决方案3】:

        散列函数最经常(但不一定总是)输出所需范围内的整数(通常是散列函数的参数)。这个整数可以用作索引。请注意,当给定不同的数据进行散列时,散列函数不能保证总是产生唯一的结果。这称为哈希冲突,哈希算法必须始终以某种方式处理它。

        至于您的具体问题,字符串如何变成数字。任何字符串都由字符(J、o、h、n ...)组成,并且字符可以解释为数字(在计算机中)。 ASCII 和 UTF 标准将某些值绑定到某些字符,因此结果是确定性的,并且在所有计算机上始终相同。因此哈希函数对这些字符进行操作,将它们处理为数字并得出另一个数字(输出)。例如,您可以简单地将所有值相加并使用模运算来限制结果值的范围。

        这将是一个非常可怕的散列函数,因为例如“ab”和“ba”会得到相同的结果。哈希函数的设计很困难,所以除非情况需要其他解决方案,否则应该使用一些现成的算法。

        【讨论】:

          【解决方案4】:

          在 MSDN 上有一篇关于哈希函数(和碰撞检测/解决)的非常好的文章:

          Part 2: The Queue, Stack, and Hashtable

          您可以跳到标题使用散列函数压缩序数索引

          有些部分是 .NET 特定的(当他们谈论 .NET 默认使用哪种哈希算法时),但大多数情况下它与语言无关。

          【讨论】:

            【解决方案5】:

            散列函数所需要的只是它在给定相同键的情况下返回相同的整数。从技术上讲,始终返回 '1' 的哈希函数是不正确的。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-10-13
              • 2016-08-04
              • 2013-12-18
              • 1970-01-01
              • 2011-06-24
              • 2012-01-31
              相关资源
              最近更新 更多