簡體   English   中英

JavaScript 數組的大 O

[英]Big O of JavaScript arrays

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) prepending。 如果使用動態擴展數組,則 O(log n) 將是這兩種情況的平均情況。

我可以期望某些事情的性能比我在這里的假設更好嗎? 我不希望任何規范中概述任何內容,但實際上,所有主要實現都可能在幕后使用優化數組。 是否有動態擴展數組或其他一些性能提升算法在起作用?

聚苯乙烯

我想知道的原因是我正在研究一些排序算法,其中大多數在描述它們的整體大 O 時似乎假設追加和刪除是 O(1) 操作。

注意:雖然這個答案在 2012 年是正確的,但如今引擎對對象和數組使用非常不同的內部表示。 這個答案可能是真的,也可能不是。

與大多數使用數組實現數組的語言相比,在 Javascript 中,數組是對象,值存儲在哈希表中,就像常規對象值一樣。 像這樣:

  • 訪問 - O(1)
  • 追加 - 攤銷 O(1)(有時需要調整哈希表的大小;通常只需要插入)
  • Prepending - O(n) 通過unshift ,因為它需要重新分配所有索引
  • 插入 - 如果值不存在,則攤銷 O(1)。 O(n) 如果您想移動現有值(例如,使用splice )。
  • 刪除 - 分攤 O(1) 刪除一個值,如果你想通過splice重新分配索引則為 O(n)。
  • 交換 - O(1)

通常,設置或取消設置字典中的任何鍵都是分攤 O(1) 的,數組也是如此,無論索引是什么。 任何需要對現有值重新編號的操作都是 O(n),因為您必須更新所有受影響的值。

保證

任何數組操作都沒有指定的時間復雜度保證。 數組的執行方式取決於引擎選擇的底層數據結構。 引擎也可能有不同的表示,並根據某些啟發式在它們之間切換。 初始數組大小可能是也可能不是這樣的啟發式。

現實

例如,V8 使用(截至目前)哈希表數組列表來表示數組。 它還對對象有各種不同的表示,因此數組和對象無法進行比較。 因此,數組訪問總是優於 O(n),甚至可能與 C++ 數組訪問一樣快。 附加是 O(1),除非您達到數據結構的大小並且必須對其進行縮放(即 O(n))。 前置更糟糕。 如果您執行諸如delete array[index]之類的操作(不要,),刪除可能會更糟。 因為這可能會迫使引擎更改其表示。

建議

將數組用於數字數據結構。 這就是他們的目的。 這就是引擎將優化它們的原因。 避免使用稀疏數組(或者,如果必須這樣做,性能會更差)。 避免使用混合數據類型的數組(因為這會使內部表示更加復雜)。

如果您真的想針對某個引擎(和版本)進行優化,請檢查其源代碼以獲得絕對答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM