【问题标题】:How double hashing works in case of the .NET Dictionary?对于 .NET 字典,双重哈希如何工作?
【发布时间】:2019-06-01 08:59:22
【问题描述】:

前几天我正在阅读that article on CodeProject

我很难理解关于 .NET Dictionary 实现的几点(考虑到实现 here 没有在 .NET Core 中进行所有优化):

  • 注意:如果会添加超过表格中的最大数量的项目 (即 7199369),resize 方法会手动搜索下一个素数 大于旧大小两倍的数字。

  • 注意:在调整大小时尺寸加倍的原因 数组是使内部哈希表操作具有渐近性 复杂。素数被用来支持 双重哈希。

所以我试着回忆十年前我和我的好朋友维基百科上的旧 CS 课程:

但是我仍然没有真正看到它首先与双散列(这是一种针对开放寻址散列表的冲突解决技术)的关系,除了 Resize() 方法是 entries 的双倍基于最小素数(基于当前/旧大小),而且我真的没有看到“加倍”大小的好处,“渐近复杂度”(我猜那篇文章的意思是 O(n) 当底层数组(条目)已满,可调整大小)。

首先,如果使用或不使用素数将大小加倍,它真的不一样吗?

其次,在我看来,.NET 哈希表在解决冲突时使用了单独的链接技术。

我想我一定错过了一些事情,我希望有人能够阐明这两点。

【问题讨论】:

  • 加倍分配大小避免 O(n) 重新分配成本,它减少到 O(log2(n))。除 LinkedList 之外的所有 .NET 容器类都使用它。来自自然的this example 很好地解释了为什么舍入到素数是有用的。
  • 我不认为 .NET 使用双重哈希,因为计算哈希码的工作委托给对象本身(至少在默认情况下),你不能问这些对象使用不同的素数或不同的散列算法。
  • 当前的实现(至少通过reference source 是字典维护一个“空闲桶列表”,并在发生冲突时通过将它们与现有桶链接在一起来重用它们。如果没有空闲槽可用,但字典未满,然后使用下一个可用条目。如果没有可用的空闲插槽,并且字典被认为已满,则调整其大小。
  • 此外,字符串得到特殊处理。当字符串上发生太多冲突时,就会使用一个新的随机字符串比较器(我不知道这里的“随机”这个词是什么意思确切地,但这是内部类名的一部分)。我假设这是为了处理您添加大量字符串的情况,这些字符串由于某种原因最终导致大量冲突,然后创建一个新的比较器,它将(希望)在新字典中分配具有较少冲突的字符串。然后使用这个新的比较器重新分配条目。
  • 然而,这一切都是实现细节。您唯一可以依赖的是它的行为与记录一致,而这些都没有记录。

标签: c# .net dictionary


【解决方案1】:

我在Reddit得到了答案,所以我想在这里总结一下:

冲突解决技术

首先,似乎冲突解决方案使用的是Separate Chaining technique 而不是Open addressing technique,因此没有Double Hashing strategy

代码如下:

private struct Entry 
{
    public int hashCode;    // Lower 31 bits of hash code, -1 if unused
    public int next;        // Index of next entry, -1 if last
    public TKey key;        // Key of entry
    public TValue value;    // Value of entry
}

只是不是为所有共享相同哈希码/索引的条目提供一个专用存储,如列表或每个存储桶之类的东西,所有内容都存储在同一个条目数组中。

质数

关于素数,答案就在这里:https://cs.stackexchange.com/a/64191/42745 都是关于倍数的:

因此,为了尽量减少碰撞,重要的是减少 m 和 K 的元素之间的公因数的数量。 取得成就?通过选择 m 为具有很少因数的数:a 素数。

基础条目数组大小加倍

通过将数组的大小增加足够数量的槽来帮助避免调用过多的调整大小操作(即副本)。

查看答案:https://stackoverflow.com/a/2369504/4636721

如果出现以下情况,哈希表不能声明“摊销固定时间插入”, 例如,调整大小是一个恒定的增量。在这种情况下 调整大小的成本(随着哈希表的大小而增长) 将使一次插入的成本与总数成线性关系 要插入的元素。因为调整大小变得越来越昂贵 随着桌子的大小,它必须“越来越少地”发生 保持插入的摊销成本不变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-13
    • 2011-06-10
    • 2014-03-24
    • 1970-01-01
    • 2011-09-11
    相关资源
    最近更新 更多