【问题标题】:Internally, how do hashes lookup the key to get the value?在内部,哈希如何查找键以获取值?
【发布时间】:2011-05-21 05:30:55
【问题描述】:

在内部,哈希如何查找键来获取值?

会是 bin 排序吗?

【问题讨论】:

  • @Gabe:我猜他的意思是:“二进制排序”
  • 我想如果他问的是字典,二分搜索是有道理的,但散列有点暗示散列。

标签: c# dictionary hash


【解决方案1】:

字典使用哈希码来计算存储条目的桶的编号。桶的数量被选择为素数,并且特定密钥的桶数被计算为密钥的哈希码以桶的数量为模。因为多个对象可以具有相同的哈希码,并且多个哈希码可以落在同一个桶中,所以当在桶中找到一个键时,还必须比较它是否相等,以确保它是正确的键。如果在bucket中发现了不正确的key,则使用错误条目的next成员来查找下一个位置来搜索所需的key。

该算法的结果是,当没有冲突时,可以非常快速地找到正确的存储桶 - O(1),但在最坏的情况下,字典中存储的条目数量可能需要线性时间。我在这里假设一个对象的哈希码可以在恒定时间内计算出来。

.NET实现中的实际代码可以通过下载参考实现源码查看,也可以使用.NET Reflector查看:

private int FindEntry(TKey key)
{
    if (key == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
    }
    if (this.buckets != null)
    {
        int num = this.comparer.GetHashCode(key) & 0x7fffffff;
        for (int i = this.buckets[num % this.buckets.Length]; i >= 0; i = this.entries[i].next)
        {
            if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
            {
                return i;
            }
        }
    }
    return -1;
}

【讨论】:

  • 然后搜索一个链表。哈希码是基于桶的数量,所以如果冲突的数量很高,桶会调整大小,并重新计算哈希。 (对吧?)
  • @John - 我会将其重写为'......冲突很高,应该调整存储桶的大小并重新计算哈希'
  • @Blankman - 请注意,在您收到的 3 个答案中,没有一个提到“bin search”
  • @Blankman - 更实际地,在存储桶中可以进行二进制搜索,但它会引入对您的对象类型的排序要求,以便可以对列表进行排序。为可以存储的对象类型添加额外(不必要的)限制并不是一个好主意。
  • 为什么要使用模数?? num % this.buckets.length 这让我有点困惑......
【解决方案2】:

哈希只是针对一个键运行的算法,它创建(希望)一个唯一值,该值指向存储项目的存储桶。因此,当您计算值以尝试检索该项目时,您希望是哈希将指向您之前保存的对象。如果没有,应该有一个指针,指示在哪里寻找下一个共享这个散列值的对象。当您找到您的物品时,它会返回。如果到达链的末端,则无法找到您的项目。

请参阅 Hash TablesHash Function 了解更完整的哈希定义。

【讨论】:

    猜你喜欢
    • 2012-11-21
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 2014-01-30
    • 2017-12-10
    • 2014-07-26
    • 2013-05-23
    • 1970-01-01
    相关资源
    最近更新 更多