前几天,我在读that article on CodeProject
我很难理解有关.NET词典的实现的一些要点(考虑实现here而不进行.NET Core中的所有优化):
注意:如果添加的项目超过表中的最大数量 (即7199369),resize方法将手动搜索下一个质数 大于旧大小两倍的数字。
注意:调整大小时将尺寸加倍的原因 数组是使内部哈希表操作具有渐近性 复杂。质数用于支持 二次哈希。
因此,我想和我的好朋友Wikipedia一起记起十年前的CS课程:
但是我仍然没有真正看到它首先与双重哈希(这是开放式地址哈希表的冲突解决技术)之间的关系,除了{{1}的Resize()方法是双重的事实之外, }基于最小素数(基于当前/旧大小)和tbh,我并没有真正看到将大小“加倍”,“渐近复杂度”的好处(我猜这篇文章的意思是O(n)基础数组(条目)已满,并且可能会调整大小)。
首先,如果在使用或不使用质数的情况下将大小加倍,是不是真的不一样?
第二,对我来说,.NET哈希表在解决冲突时使用一种单独的链接技术。
我想我一定错过了一些事情,我想找一个可以阐明这两点的人。
答案 0 :(得分:0)
我在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
如果,哈希表无法要求“摊销固定时间插入”, 例如,调整大小以恒定的增量进行。在这种情况下 调整大小的成本(随散列表的大小而增加) 会使一次插入的费用在 要插入的元素。因为调整大小变得越来越昂贵 随着表的大小,它必须“越来越少地发生” 保持摊销成本不变。