为什么使用数组来实现“列表”而不是哈希表?

时间:2010-02-15 16:29:18

标签: arrays language-agnostic list data-structures hashtable

考虑一个数组与一个哈希表,其中键只是列表的整数索引。

它们的平均情况插入,查找和删除big-O界限都是O(1)恒定时间。我知道你可以通过一个数组在缓存局部获得一些低级别的胜利,并且哈希表操作有一个边际(大部分是常量的)开销,但哈希表可以免费获得稀疏性,这在某些应用程序中是一个巨大的胜利。

我错过了哪些其他重要(或小)对比?

背景:我在采访编程候选人时有时会讨论这个问题。通常上下文是“如何在JS VM中实现Javascript数组类型?”对于密集的数据,我支持原生数组,但我希望有更好的推理而不是“看起来不像矫枉过正”的直觉。

4 个答案:

答案 0 :(得分:5)

数组是jsut哈希表的特例,其中哈希函数非常简单

f(x) := x;

并且使用的模数与数据字大小相同(因此也就是数组大小)。

如果你不允许非唯一值,你不需要“下一个”指针和瞧,我们有一个数组。

由于缺少复杂的散列函数和模数计算,这非常快,但只有在数组可以保持较小时才适用(非常大的数组,其中有大量空白位置会浪费内存资源,并可能触发令人讨厌的事情,如交换/垃圾到磁盘)。

答案 1 :(得分:2)

当你从想要实现Javascript的伪数组行为的人的角度来看它时,你是正确的,哈希表是更好的方法,特别是。因为Javascript数组没有固定的长度,并且需要能够容纳任何索引的条目。 Javascript中的数组看起来像数组,但表现得更像哈希表。

但是在一种更接近机器的语言中,使用真实数组可以有效存储在数组中的数据的性能和空间优势是非常值得注意的,特别是因为使用哈希表的好处是相当的限于稀疏数组,这不是你应该或应该使用数组。实际上,使用具有整数键的哈希表更好。

在所有情况下,插入,查找和删除对于数组也是O(1),但是具有比哈希表低得多的常量O(这不仅仅是因为缓存局部性)。并且数组每个条目需要的空间更少。如果您希望以下列条目相应地更改其索引的方式删除和插入条目,那么它将是O(n),其中n表示需要移动的条目数,但它也将是O(n)哈希表要做到这一点,并再次使用更高的常量开销。这种操作可以让您更好地使用链接列表。同样增长一个数组比增加一个可能需要重新整理所有条目的哈希表的成本更低。

所有不同的收藏类型都有其特定的优点和缺点。这就是为什么有这么多使用它们的原因。

答案 2 :(得分:1)

因为列表通常是有序的,而哈希表则不是。在将元素添加到列表中并期望排序保持一致的上下文中,哈希表不保证在数组保留排序时返回的顺序。

答案 3 :(得分:0)

因为哈希函数不是免费的。线性因素很重要。最糟糕的案例时间很重要。计算说明。

对于您引用的特定情况,这是Javascript的底层实现,可能会有太多其他开销来消除这些问题。尽管如此,如果有人试图通过简单的数字键做一些真正击中阵列的数学,那么阵列必须更好。