Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.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
Performance 为什么我们要使用链表来解决哈希表中的冲突? 我想知道为什么很多语言(java,C++,python,perl等)使用链表来实现哈希表,以避免冲突而不是数组? 我的意思是,我们应该使用数组,而不是一堆堆的链表。 如果关注的是数组的大小,那么这意味着我们有太多的冲突,因此我们已经有了哈希函数的问题,而不是解决冲突的方式。我误解了什么吗?_Performance_Algorithm_Data Structures_Hashtable - Fatal编程技术网

Performance 为什么我们要使用链表来解决哈希表中的冲突? 我想知道为什么很多语言(java,C++,python,perl等)使用链表来实现哈希表,以避免冲突而不是数组? 我的意思是,我们应该使用数组,而不是一堆堆的链表。 如果关注的是数组的大小,那么这意味着我们有太多的冲突,因此我们已经有了哈希函数的问题,而不是解决冲突的方式。我误解了什么吗?

Performance 为什么我们要使用链表来解决哈希表中的冲突? 我想知道为什么很多语言(java,C++,python,perl等)使用链表来实现哈希表,以避免冲突而不是数组? 我的意思是,我们应该使用数组,而不是一堆堆的链表。 如果关注的是数组的大小,那么这意味着我们有太多的冲突,因此我们已经有了哈希函数的问题,而不是解决冲突的方式。我误解了什么吗?,performance,algorithm,data-structures,hashtable,Performance,Algorithm,Data Structures,Hashtable,策略1 使用(小)数组,一旦发生冲突,这些数组将被实例化并随后填充。1个堆操作用于分配阵列,然后再为N-1个分配空间。如果该存储桶不再发生冲突,则N-1个条目的容量将被浪费。列表获胜,如果冲突很少,则不会仅为存储桶上有更多溢出的可能性分配多余内存。移除物品也更昂贵。在阵列中标记已删除的点或将其后面的内容移动到前面。如果阵列已满怎么办?数组的链接列表或调整数组大小 使用数组的一个潜在好处是进行排序插入,然后在检索时进行二进制搜索。链表方法无法与之竞争。但这是否有回报取决于写入/检索比率。写作的频率

策略1

使用(小)数组,一旦发生冲突,这些数组将被实例化并随后填充。1个堆操作用于分配阵列,然后再为N-1个分配空间。如果该存储桶不再发生冲突,则N-1个条目的容量将被浪费。列表获胜,如果冲突很少,则不会仅为存储桶上有更多溢出的可能性分配多余内存。移除物品也更昂贵。在阵列中标记已删除的点或将其后面的内容移动到前面。如果阵列已满怎么办?数组的链接列表或调整数组大小

使用数组的一个潜在好处是进行排序插入,然后在检索时进行二进制搜索。链表方法无法与之竞争。但这是否有回报取决于写入/检索比率。写作的频率越低,回报就越大

战略2

使用列表。你要为你得到的付出代价。1冲突=1堆操作。没有急切的假设(以及记忆方面的代价)“还会有更多”。在冲突列表中进行线性搜索。更便宜的删除。(这里不算免费的()。考虑数组而不是列表的一个主要动机是减少堆操作的数量。有趣的是,一般的假设似乎是它们很便宜。但实际上,没有多少人知道一次分配需要多少时间,比如遍历列表寻找匹配项

战略3

既不使用数组也不使用列表,而是将溢出项存储在哈希表中的另一个位置。上次我在这里提到这一点,我有点不高兴。优点:0内存分配。如果表的填充级别确实很低,并且只有很少的碰撞,则可能效果最好

摘要


确实有许多选择和取舍可供选择。通用哈希表实现(如标准库中的实现)无法对写/读比率、哈希键质量、用例等做出任何假设。另一方面,如果哈希表应用程序的所有这些特征都已知(并且值得付出努力),很有可能创建一个哈希表的优化实现,该哈希表是为应用程序所需的一组权衡而定制的。

原因是,这些列表的预期长度很小,在绝大多数情况下只有零个、一个或两个条目。然而,在一个非常糟糕的哈希函数的最坏情况下,这些列表也可能变得任意长。即使这种最坏的情况不是哈希表优化的情况,它们仍然需要能够优雅地处理它

现在,对于基于数组的方法,需要设置最小数组大小。而且,如果初始数组大小不是零,那么由于所有的空列表,您已经有了很大的空间开销。最小数组大小为2意味着您浪费了一半的空间。当数组变满时,您需要实现逻辑来重新分配数组,因为您不能设置列表长度的上限,您需要能够处理最坏的情况

在这些约束条件下,基于列表的方法效率更高:它只有节点对象的分配开销,大多数访问具有与基于数组的方法相同的间接寻址量,并且更易于编写

我并不是说写一个基于数组的实现是不可能的,但是它比基于列表的方法要复杂得多,效率也要低得多

<>强>为什么为什么很多语言(java,C++,python,perl等)使用链表实现哈希表,以避免冲突而不是数组?< /p> 我几乎可以肯定,至少对大多数人来说,这些“许多”语言:

这些语言的哈希表的最初实现者遵循KNUTH/经典算法书中的经典算法描述,甚至没有考虑到这些细微的实现选择。 一些意见:

  • 即使使用冲突解决,而不是,比如说,用于“最通用的哈希表实现”,也是一个非常值得怀疑的选择。我个人的信念——这不是正确的选择

  • 当哈希表的负载因子非常低时(应该在几乎99%的哈希表使用中选择),建议的方法之间的差异几乎不会影响总体数据结构性能(正如cmaster在其答案的开头所解释的,delnan在注释中有意义地进行了细化)。由于语言中的通用哈希表实现不是为高密度而设计的,“链表vs数组”对它们来说不是一个紧迫的问题

  • 回到主题问题本身,我看不出有任何概念上的理由说明链表比数组更好。我可以很容易地想象,事实上,阵列在现代硬件上更快,在现代语言运行时/操作系统中使用现代内存分配器消耗更少内存。尤其是当哈希表的键是基元或复制的结构时。你可以在这里找到支持这一观点的一些论据:

    但是找到正确答案的唯一方法(对于特定的CPU、操作系统、内存分配器、虚拟机及其垃圾收集算法,以及哈希表用例/工作负载!)是实现这两种方法并进行比较

我是不是误解了什么

不,你不需要我
0=367790 1=367843 2=184192 3=61200 4=15370 5=3035 6=486 7=71 8=11 9=2
0=367664 1=367788 2=184377 3=61424 4=15231 5=2933 6=497 7=75 8=10 10=1
0=367717 1=368151 2=183837 3=61328 4=15300 5=3104 6=486 7=64 8=10 9=3
0=36787653 1=36788486 2=18394273 3=6130573 4=1532728 5=306937 6=51005 7=7264 8=968 9=101 10=11 11=1