【发布时间】:2012-07-15 21:22:59
【问题描述】:
JavaScript 中的数组很容易通过添加和删除项来修改。它在某种程度上掩盖了大多数语言数组是固定大小的事实,并且需要复杂的操作来调整大小。似乎 JavaScript 可以轻松编写性能不佳的数组代码。这就引出了一个问题:
在数组性能方面,我可以从 JavaScript 实现中获得什么性能(就大 O 时间复杂度而言)?
我假设所有合理的 JavaScript 实现最多有以下大 O。
- 访问 - O(1)
- 追加 - O(n)
- 前置 - O(n)
- 插入 - O(n)
- 删除 - O(n)
- 交换 - O(1)
JavaScript 允许您使用new Array(length) 语法将数组预填充到特定大小。 (额外的问题:以这种方式创建一个数组 O(1) 还是 O(n))这更像是一个传统的数组,如果用作一个预先确定大小的数组,可以允许 O(1) 追加。如果添加了循环缓冲区逻辑,则可以实现 O(1) 前置。如果使用动态扩展数组,O(log n) 将是这两种情况的平均情况。
在某些方面,我可以期待比我的假设更好的性能吗?我不希望在任何规范中概述任何内容,但实际上,所有主要实现都可能在幕后使用优化的数组。是否有动态扩展数组或其他一些性能提升算法在起作用?
附言
我想知道这是因为我正在研究一些排序算法,其中大多数在描述它们的整体大 O 时似乎假设追加和删除是 O(1) 操作。
【问题讨论】:
-
具有大小的数组构造函数在现代 JavaScript 实现中几乎没有用处。在那个单一的参数形式中,它几乎什么都不做。 (它设置了
.length,仅此而已。)数组与普通的 Object 实例并没有太大区别。 -
设置
length属性和预分配空间是完全不同的两件事。 -
@Pointy:当我期望在
new Array(10)上设置array[5]是 O(1) 时,我是否期望过高? -
虽然ECMAScript没有定义一个Array对象是如何实现的(它只定义了一些语义规则),但不同的实现很可能会针对预期的情况进行优化(例如对于小于一些 n 的数组有一个“真正的数组”支持)。我对实现不是那么精通,但如果这不是在某个地方完成的话,我会真的很惊讶 ...
-
@KendallFrey “最佳答案”可能会为不同的 n / 访问模式编写一些 jsperf 测试用例,看看结果如何;-)
标签: javascript arrays algorithm big-o time-complexity