web-dev-qa-db-ja.com

JavaScript配列の大きなO

JavaScriptの配列は、アイテムを追加および削除することで非常に簡単に変更できます。ほとんどの言語配列は固定サイズであり、サイズを変更するには複雑な操作が必要であるという事実を多少隠しています。 JavaScriptを使用すると、パフォーマンスの低い配列コードを簡単に記述できるようになります。これは質問につながります:

配列のパフォーマンスに関してJavaScriptの実装からどのようなパフォーマンス(大きなO時間の複雑さに関して)を期待できますか?

すべての合理的なJavaScript実装には、少なくとも次の大きなOがあると思います。

  • アクセス-O(1)
  • 追加-O(n)
  • プリペンディング-O(n)
  • 挿入-O(n)
  • 削除-O(n)
  • スワップ-O(1)

JavaScriptでは、new Array(length)構文を使用して、配列を特定のサイズに事前に入力できます。 (ボーナス質問:この方法で配列を作成していますO(1) or O(n))これは従来の配列に似ています。事前にサイズ設定された配列として、O(1)追加を許可できます。循環バッファロジックが追加された場合、O(1) prepending.If動的に拡張する配列が使用され、O(log n)は両方の平均的なケースになります。

ここでの仮定よりも、いくつかのことでより良いパフォーマンスを期待できますか?仕様に概要が記載されているとは思いませんが、実際には、すべての主要な実装が舞台裏で最適化された配列を使用している可能性があります。動的に拡張する配列やその他のパフォーマンスを向上させるアルゴリズムが動作していますか?

追伸.

私がこれを疑問に思っているのは、いくつかのソートアルゴリズムを研究しているからです。それらのほとんどは、全体の大きなOを記述するときに、追加と削除がO(1)操作であると仮定しています.

95
Kendall Frey

JavaScriptで配列を使用して配列を実装するほとんどの言語とは対照的に、配列はオブジェクトであり、値は通常のオブジェクト値と同様にハッシュテーブルに格納されます。など:

  • アクセス-O(1)
  • 追加-償却O(1)(ハッシュテーブルのサイズ変更が必要になる場合があります。通常、挿入のみが必要です)
  • プリペンディング-O(n) via unshift経由、すべてのインデックスの再割り当てが必要なため
  • 挿入-償却O(1)値が存在しない場合。O(n)既存の値をシフトする場合(たとえば、splice)。
  • 削除-Amortized O(1)値を削除するには、O(n) spliceを介してインデックスを再割り当てする場合。
  • スワップ-O(1)

一般に、dictのキーの設定または設定解除はO(1)で償却され、インデックスが何であるかに関係なく、配列にも同じことが当てはまります。既存の値に番号を付け直す必要がある操作は、O(n))です。これは、影響を受けるすべての値を更新する必要があるためです。

103
Nick Johnson