これは、 Janoma による csでの質問 の再投稿です。完全なクレジットと彼またはcs.SEへの甘やかし。
標準アルゴリズムコースでは、quicksortは平均でO(n log n)、最悪の場合はO(n²)であると教えられています。同時に、最悪の場合のO(n log n)(mergesortおよびheapsort)、および最良の場合の線形時間(bubblesort)と同様ですが、いくつかの追加のニーズがありますメモリの。
いくつかの実行時間 をざっと見てみると、quicksortは他のものほど効率的ではないと言うのは自然なことです。
また、基本的なプログラミングコースでは、メモリの使用量が多すぎるなどの理由で、再帰は一般的にあまりよくないことを考慮してください。したがって、これは(実際の議論ではありませんが)、クイックソートはそれは再帰的なアルゴリズムなので本当に良いです。
では、なぜ実際にクイックソートが他のソートアルゴリズムよりも優れているのですか?現実世界の構造と関係があるのでしょうか?データ?コンピュータでのメモリの動作と関係がありますか?一部のメモリが他のメモリよりもはるかに高速であることは知っていますが、それがこの直観に反するパフォーマンスの真の理由であるかどうかはわかりません(理論的な見積もりと比較した場合)。
クイックソートが他のソートアルゴリズムよりも実際に優れていることに私は同意しません。
ほとんどの目的で、 Timsort -マージソート/挿入ソートのハイブリッド。これは、ソートしたデータがほとんどソートされているか、逆ソートされていることが多いことを利用しています。
最も単純なクイックソート(ランダムピボットなし)は、この潜在的に一般的なケースをO(N ^ 2)(ランダムピボットでO(N lg N)に削減)として扱いますが、TimSortはO(N)でこれらのケースを処理できます。
これらの benchmarks によると、C#では built-in quicksort とTimSortを比較すると、Timsortはほとんどソートされたケースで大幅に高速になり、ランダムデータのケースでわずかに高速になり、TimSortは比較関数が特に遅い場合はより良いです。私はこれらのベンチマークを繰り返していませんが、ランダムデータのいくつかの組み合わせでクイックソートがTimSortをわずかに上回った場合、またはC#の組み込みのソート(クイックソートに基づく)で風変わりなものがあり、それが遅くなっている場合も驚くことではありません。ただし、TimSortには、データが部分的に並べ替えられる可能性がある場合に明確な利点があり、データが部分的に並べ替えられていない場合の速度に関しては、クイックソートとほぼ同じです。
TimSortには、クイックソートとは異なり、安定したソートであるという追加のボーナスもあります。 TimSortの唯一の欠点は、通常の(高速)実装でO =(lg N)メモリに対してO(N))を使用することです。
係数は他の既知のアルゴリズムよりも小さいため、クイックソートは高速であると見なされます。その理由も証明もありません。小さな係数のアルゴリズムが見つからなかっただけです。他のアルゴリズムにもO(n log n)時間があることは事実ですが、実際には係数も重要です。
小さなデータ挿入ソート(O(n2))は、数学関数の性質上、より高速です。これは、マシンごとに異なる特定の係数に依存します。 (最終的には、実際に実行されているのはアセンブリのみです。)したがって、実際には、クイックソートと挿入ソートのハイブリッドが最も速いと思います。
クイックソートは、他のすべてのソートアルゴリズムよりも優れているわけではありません。たとえば、ボトムアップヒープソート( Wegener 2002 )は、適度な量のデータのクイックソートよりも優れており、インプレースアルゴリズムでもあります。また、実装も簡単です(少なくとも、いくつかの最適化されたクイックソートバリアントよりも難しくありません)。
それはあまり知られていないだけでなく、多くの教科書には載っていないので、クイックソートほど人気がない理由が説明されるかもしれません。
最悪の場合や時間の複雑さだけに集中するべきではありません。それは最悪というより平均であり、それは時間についてですandスペース。
クイックソート:
また、大きな[〜#〜] o [〜#〜]表記では定数は考慮されませんが、実際には、アルゴリズムが数倍速くなります。 ((nlogn)は、そのアルゴリズムが[〜#〜] k [ 〜#〜]nlog(n)、ここで[〜# 〜] k [〜#〜]は定数です。クイックソートは、比較ソートアルゴリズムで、最低[〜#〜] k [〜#〜]を使用します。
クイックソートは、適度に速く、適度に速く、実装が容易であるため、多くの場合、良い選択です。
大量のデータを非常に迅速にソートすることに真剣に取り組んでいる場合は、MergeSortのバリエーションを使用することをお勧めします。これにより、外部ストレージを利用したり、複数のスレッドやプロセスを利用したりできますが、コードの作成は簡単ではありません。
アルゴリズムの実際のパフォーマンスは、プラットフォーム、言語、コンパイラ、実装の詳細へのプログラマの注意、特定の最適化の取り組みなどに依存します。したがって、クイックソートの「定数係数の利点」はあまり明確に定義されていません。これは、現在利用可能なツールに基づく主観的な判断であり、実際に比較パフォーマンスの調査を行った人による「同等の実装作業」の大まかな見積もりです。 。
とは言っても、クイックソートは単純であり、その再帰構造が比較的キャッシュフレンドリーであるため、(ランダム化された入力に対して)うまく機能すると私は考えています。一方、最悪の場合はトリガーが簡単なので、クイックソートの実際の使用は、教科書の説明が示すよりも複雑にする必要があります。したがって、イントロソートなどの変更されたバージョンです。
時間の経過とともに、支配的なプラットフォームが変化すると、さまざまなアルゴリズムが(明確に定義されていない)相対的な利点を獲得または失う可能性があります。相対的なパフォーマンスに関する従来の知識はこの変化にかなり遅れている可能性があるため、アプリケーションに最適なアルゴリズムが本当にわからない場合は、両方を実装してテストする必要があります。