web-dev-qa-db-ja.com

挿入ソートを使用する正当な理由はありますか?

汎用ソートの場合、答えはノーと思われます。クイックソート、マージソート、およびヒープソートは、平均シナリオと最悪のシナリオでパフォーマンスが向上する傾向があるためです。ただし、挿入ソートはインクリメンタルソートでExcelに表示されます。つまり、リストをソートしたまま、特に挿入ソートがリンクリストとして実装されている場合(O(log n)O(n)に対する平均ケース。ただし、ヒープはインクリメンタルソートと同じように(またはほぼ)実行できるようです(ヒープに単一の要素を追加または削除すると、最悪の場合O(log n)のシナリオになります)。では、挿入ソートは、他の比較ベースのソートアルゴリズムまたはヒープに対して正確に何を提供する必要があるのでしょうか。

41
CS Student

http://www.sorting-algorithms.com/insertion-sort から:

これは、O(n2)最悪の場合、挿入ソートは、データがほぼソートされている場合(適応性があるため)または問題のサイズが小さい場合(オーバーヘッドが低いため)のいずれかのアルゴリズムです。

これらの理由により、また安定しているため、挿入ソートは、マージソートやクイックソートなどのオーバーヘッドの高い分割統治ソートアルゴリズムの再帰的な基本ケース(問題サイズが小さい場合)としてよく使用されます。

56
guns

アルゴリズムの分析における重要な概念は、漸近的分析です。漸近実行時間が異なる2つのアルゴリズムの場合(1つのO(n ^ 2)と1つのO(nlogn)のように、それぞれ挿入ソートとクイックソートの場合と同様)一方が他方よりも速いことは明らかではありません。

この種の分析の重要な違いは、十分に大きなNの場合、1つのアルゴリズムが別のアルゴリズムよりも高速になることです。アルゴリズムをO(nlogn)のような項まで分析すると、定数が削除されます。アルゴリズムの実行を現実的に分析する場合、これらの定数はnが小さい状況でのみ重要になります。

これはどういう意味ですか?つまり、特定の小さなnの場合、一部のアルゴリズムはより高速です。 EmbeddedGurus.netの article には、限られたスペース(16k)と限られたメモリシステムの場合に、さまざまなソートアルゴリズムを選択することに関する興味深い見方が含まれています。もちろん、この記事は20個の整数のリストのソートのみを参照しているため、nのより大きな次数は関係ありません。短いコードと少ないメモリ消費(そして再帰の回避)は、最終的にはより重要な決定でした。

挿入ソートはオーバーヘッドが低く、かなり簡潔に書くことができ、2つの主要な利点があります。安定していることと、入力がほぼソートされている場合に実行速度がかなり速いことです。

17
Anthony

はい、挿入ソートまたはそのバリアントのいずれかを使用する理由があります。

ここでの他の回答の並べ替えの選択肢(クイックソートなど)では、データが既にメモリにあり、準備ができていると想定しています。

ただし、低速の外部ソース(ハードドライブなど)から大量のデータを読み取ろうとすると、明らかにボトルネックがデータチャネルまたはドライブ自体であるため、大量の時間が無駄になります。 CPUについていけません。読み取り中に自然な一連の待機が発生します。これらの待機はwasted CPU cycleを使用しない限りsortですあなたが行くと

たとえば、これに対する解決策を次のようにするとします。

  1. 専用ループの大量のデータをメモリに読み込む
  2. そのデータを並べ替える

2つのスレッドで以下を実行する場合よりも時間がかかる可能性が非常に高くなります。

スレッドA:

  1. データを読む
  2. データムをFIFOキューに入れる
  3. (ドライブからデータがなくなるまで繰り返す)

スレッドB:

  1. FIFOキューからデータを取得します
  2. ソート済みリストの適切な場所に挿入します
  3. (キューが空になり、スレッドAが「完了」と言うまで繰り返します)。

...上記では、無駄な時間を使用することができます。注:スレッドBは、スレッドAの進行を妨げません。

データが完全に読み取られるまでに、データはソートされ、使用できる状態になります。

10
user4229245

ほとんどの並べ替え手順では、クイックソートを使用してから、非常に小さなデータセットに対して挿入ソートを使用します。

4
BobbyShaftoe

はい、

挿入リストは、短いリストではクイックソートよりも優れています。

実際、最適なクイックソートには、停止するサイズのしきい値があり、配列全体がしきい値を超えて挿入ソートによってソートされます。

また...

スコアボードを維持するには、Binary Insertion Sortが最適です。

このページ を参照してください。

1
JohnPaul

ソートされたリストを維持することについて話している場合、ある種のツリーに勝る利点はなく、ただ遅いだけです。

まあ、多分それはより少ないメモリを消費するか、より単純な実装です。

ソートされたリストへの挿入にはスキャンが含まれます。つまり、各挿入はO(n)であるため、nアイテムのソートはO(n ^ 2)になります。

バランスの取れたツリーなどのコンテナーへの挿入は、通常、log(n)です。したがって、ソートはO(n log(n))であり、もちろんより優れています。

しかし、小さなリストの場合、ほとんど違いはありません。ライブラリなしで自分で作成する必要がある場合、リストが小さい場合、またはパフォーマンスを気にしない場合は、挿入ソートを使用できます。

1
MarkR

小さな配列の場合、挿入ソートはクイックソートよりも高速に実行されます。 Java 7およびJava 8は、デュアルピボットクイックソートを使用してプリミティブデータタイプをソートします。デュアルピボットクイックソート出力は、一般的なシングルピボットを実行しますクイックソートデュアルピボットクイックソートのアルゴリズムによると:

  1. 小さな配列(長さが27未満)の場合は、挿入ソートアルゴリズムを使用します。
  2. 2つのピボットを選択します。

明確に挿入ソートアウトは小さな配列に対してクイックソートを実行するので、27未満の配列の挿入ソートに切り替えます。その理由は、挿入ソートに再帰がないためです。

ソース: http://codeblab.com/wp-content/uploads/2009/09/DualPivotQuicksort.pdf

0
Kangkan Lahkar