クイックソートが実際に他のソートアルゴリズムよりも優れているのはなぜですか?


31

これはJanomaによるcs.SE に関する質問の再投稿です。彼またはcs.SEへの完全なクレジットと台無し。

標準アルゴリズムコースでは、クイックソートは平均でO(n log n)であり、最悪の場合はO(n²)であると教えられています。同時に、最悪の場合(mergesortheapsortのような)O(n log n)であり、最高の場合(bubblesortのような)でも線形時間であるが、メモリの追加の必要性がある他のソートアルゴリズムが研究されています。

いくつかの実行時間をひと目見た後、クイックソート他の効率ほど効率的であってはならないと言うのが自然です。

また、学生は基本的なプログラミングコースで、再帰があまりにも多くのメモリを使用するなどの理由であまり良くないことを学ぶと考えてください。したがって(これは本当の議論ではありませんが)、これはクイックソートがそうではないという考えを与えますそれは再帰アルゴリズムであるため、本当に良いです。

それでは、実際にクイックソートが実際に他のソートアルゴリズムよりも優れているのはなぜですか?実世界のデータの構造に関係していますか?コンピューターでのメモリの動作方法に関係していますか?一部のメモリは他のメモリよりもはるかに高速であることは知っていますが、それがこの直感に反するパフォーマンスの本当の理由であるかどうかはわかりません(理論的な推定と比較した場合)。


3
クイックソートの評判は、キャッシュが存在しなかったときから始まります。
AProgrammer

9
「実際にクイックソートが他のソートアルゴリズムよりも優れているのはなぜですか?」本当ですか?このステートメントを使用して、参照している実際の実装を示してください。コミュニティは、その特定の実装が動作する理由を説明します。他のすべては、存在しないプログラムについての大胆な推測につながります。
ドックブラウン

1
@DocBrown:多くのライブラリで多くのQuicksort(またはそのバリアント)実装が選択されています。そのため、実装に関係なく、Quicksortを高速にするアルゴリズムについて何かがあるかもしれません。
ラファエル

1
完全を期すために誰かがこれを言わなければならないので、私はそうします:Quicksortは(通常)安定していません。このため、使用したくない場合があります。また、この理由から、デフォルトの並べ替えは、それが望みのものであってもクイック並べ替えではない場合があります。
-RalphChapin

1
@Raphael:多くの場合、クイックソートと呼ばれるものは、実際にはイントロソート(C ++標準ライブラリで使用されるafaik)のようなバリエーションであり、純粋なクイックソートではありません。
ジョルジオ

回答:


21

クイックソートが実際には他のソートアルゴリズムよりも優れていることに同意しません。

ほとんどの目的で、Timsort-マージソート/挿入ソートのハイブリッドで、ソートするデータがほとんどソート済みまたは逆ソートで始まることが多いという事実を利用します。

最も単純なクイックソート(ランダムピボットなし)は、この潜在的に一般的なケースをO(N ^ 2)(ランダムピボットでO(N lg N)に削減)として扱いますが、TimSortはこれらのケースをO(N)で処理できます。

組み込みのクイックソートとTimSortを比較するC#のこれらのベンチマークによると、Timsortはほとんどソートされたケースで非常に速く、ランダムデータのケースでわずかに速く、比較関数が特に遅い場合はTimSortが良くなります。これらのベンチマークを繰り返していませんが、ランダムデータの組み合わせでクイックソートがTimSortをわずかに上回るか、C#の組み込みソート(クイックソートに基づく)に速度が低下するような奇妙な何かがあったとしても驚かないでしょう。ただし、TimSortには、データが部分的に並べ替えられる場合に明確な利点があり、データが部分的に並べ替えられない場合の速度の点では、クイックソートとほぼ同じです。

TimSortには、クイックソートとは異なり、安定したソートであるという追加のボーナスもあります。TimSortの唯一の欠点は、通常の(高速)実装でO(N)メモリとO(lg N)メモリを使用することです。


18

係数は他の既知のアルゴリズムよりも小さいため、クイックソートはより高速であると見なされます。その理由や証拠はありませんが、より小さい係数のアルゴリズムは見つかりませんでした。他のアルゴリズムにもO(n log n)時間があることは事実ですが、現実の世界では係数も重要です。

小さいデータ挿入ソート(O(n 2)と見なされるもの)の場合、数学関数の性質により高速であることに注意してください。これは、マシンごとに異なる特定の係数に依存します。(最後には、実際に実行されるのはアセンブリのみです。)実際には、クイックソートと挿入ソートのハイブリッドが実際に最も速いと思うことがあります。


7
+右。教師は、一定の要因が桁違いに変化する可能性があるという事実をよりよく認識する必要があります(私は教師でした)。そのため、ビッグOに関係なく、パフォーマンスチューニングのスキルは本当に重要です。問題は、彼らが指導保つあるgprofのを、彼らは間違ったアプローチ180度でカリキュラムにその箇条書き過ぎて取得する必要がありますという理由だけで、。
マイクダンラベイ

2
「それには理由も賛成もありません」:確かにあります。深く掘り下げると、理由がわかります。
ジル 'SO-悪であるのをやめる

2
@B Seven:O(n log n)ソートアルゴリズムの多くを単純化するために、n個のアイテムをソートするために、ソートループの(n log n)反復があります。係数は、ループの各サイクルにかかる時間です。nが本当に大きい(少なくとも数千)場合、たとえ係数が巨大であっても、係数はO()ほど重要ではありません。ただし、nが小さい場合、係数が重要になります。10個のアイテムのみを並べ替える場合、これが最も重要になる可能性があります。
マットギャラガー

4
@MikeDunlavey-良い例は、ピラミッドの構築がO(n)である一方で、それらの写真を並べ替えるのはO(n ln n)ですが、より速いことです!
マーティンベケット

2
heapsortやmergesortなどの保証されたO(n log n)アルゴリズムがあるため、漸近的な最悪の場合、Quicksortは最高の速さでさえ等しくありません。しかし、実際のパフォーマンスでは、一部のクイックソートバリアントは非常に優れています。ただし、「係数が小さい」というのは、「速いので速い」というようなものです。なぜ定数因子はそれほど小さいのですか?主要な理由は、クイックソートがローカリティの観点から非常に優れているためです-キャッシュを非常に有効に使用します。Mergesortのローカリティも優れていますが、インプレースで行うのは非常に困難です。
Steve314

16

クイックソートは、他のすべてのソートアルゴリズムを上回るものではありません。たとえば、ボトムアップヒープソート(Wegener 2002)は、適度な量のデータに対してクイックソートよりも優れており、インプレースアルゴリズムでもあります。実装も簡単です(少なくとも、最適化されたクイックソートバリアントより難しくありません)。

あまり知られていないだけでなく、多くの教科書にも載っていないので、クイックソートほど人気が​​ない理由を説明できます。


+1:いくつかのテストを実行しましたが、実際、マージソートは、大きな配列(> 100000要素)のクイックソートよりも間違いなく優れていました。ヒープソートはマージソートよりわずかに劣っていました(ただし、マージソートにはより多くのメモリが必要です)。クイックソートと呼ばれるものは、多くの場合、イントロソートと呼ばれるバリエーションです。再帰の深さが特定の制限を超えると、ヒープソートにフォールバックするクイックソートです。
ジョルジオ

@Giorgio:クイックソートをいくつかの方法で変更して改善することができます。たとえば、ここを参照してください:algs4.cs.princeton.edu/23quicksortその改善を試みましたか?
ドックブラウン

興味深いことに、本に関する詳細を読むために本\サイトへの参照を作成できますか?(できれば本)
Ramzi Kahil

@Martin:ボトムアップヒープソートについてですか?さて、私は上記の参照を与えました。無料のリソースが必要な場合は、ドイツのウィキペディアにそれに関する記事があります(de.wikipedia.org/wiki/BottomUp-Heapsort)。ドイツ語を話さなくても、C99の例を読むことができると思います。
ドックブラウン

7

最悪のケースや時間の複雑さだけに集中すべきではありません。それは最悪というよりも平均に関するものであり、時間空間に関するものです。

クイックソート:

  • 有する平均(Θの時間複雑さをNログN)。
  • Θ(log n)のスペースの複雑さで実装できます。

また、大きなO表記は定数を考慮していないことを考慮してください。しかし、実際には、アルゴリズムが数倍高速であれば、違いが生じます。Θ(n log n)は、アルゴリズムがK  n  log(n)で実行されることを意味します。Kは定数です。Quicksortは、K が最小 の比較ソートアルゴリズムです。


1
@Gilles:単純なアルゴリズムであるため、Kが低くなっています。
バルテック

5
WTF?これは意味がありません。アルゴリズムの単純さは、その実行速度とは関係ありません。選択ソートは、クイックソートよりも簡単であり、高速にはなりません。
ジル 'SO-悪であるのをやめる

1
@Gilles:どんな場合(最悪、平均、最高)でも選択ソートはO(n ^ 2)です。ですから、それがどれほど単純であっても関係ありません。クイックソートは、平均的なケースではO(n log n)であり、O(n log n)avgのすべてのアルゴリズムの中で最も単純なものです。
バルテック

1
@Gilles:他のものが等しい場合、シンプルさはパフォーマンスを向上させます。それぞれがそれぞれの内部ループの(K n log n)反復を行う2つのアルゴリズムを比較しているとします。ループごとの処理を少なくする必要があるアルゴリズムにはパフォーマンス上の利点があります。
12

1
@comingstorm:あなたの声明はトートロジーであるようにフレーズされていますが、それは「単純さ」に関係していません。たとえば、Quicksortのより複雑なバリアント(大文字と小文字の区別!)があり、実行時間が短くなります(理論と実践の両方で)。
ラファエル

5

クイックソートは、適度に高速で、適度に迅速かつ簡単に実装できるため、多くの場合、適切な選択です。

大量のデータを非常に迅速にソートすることを真剣に考えているなら、おそらくMergeSortを少し変更した方が良いでしょう。これにより、外部ストレージを活用したり、複数のスレッドやプロセスを利用したりすることができますが、コードは簡単ではありません。


1

アルゴリズムの実際のパフォーマンスは、プラットフォーム、言語、コンパイラ、実装の詳細に対するプログラマの注意、特定の最適化の努力などに依存します。したがって、クイックソートの「定数要因の利点」はあまり明確ではありません。現在利用可能なツールに基づいた主観的な判断であり、実際に比較パフォーマンス調査を行う人による「同等の実装作業」の概算です。 。

そうは言っても、クイックソートは単純であり、その再帰構造は比較的キャッシュに優しいため、(ランダム化された入力に対して)うまく機能すると考えています。一方、最悪のケースは簡単にトリガーできるため、クイックソートの実際の使用は、教科書の説明が示すよりも複雑である必要があります。したがって、introsortなどの修正バージョンです。

時間が経つにつれて、支配的なプラットフォームが変化するにつれて、さまざまなアルゴリズムが(不明確な)相対的な優位性を獲得または失う可能性があります。相対的なパフォーマンスに関する従来の知恵は、このシフトに遅れをとる可能性があるため、アプリケーションに最適なアルゴリズムが本当に不明な場合は、両方を実装してテストする必要があります。


他の人が関係している「より小さい定数」は、正式な分析、つまり比較やスワップの数に関係していると思います。これは非常に明確に定義されていますが、これがどのようにランタイムに変換されるかは不明です。同僚は現在、実際にいくつかの研究を行っています。
ラファエル

私の印象では、それは一般化されたパフォーマンスに関するものでしたが、私も期待しません。あなたは正しいですが、比較が特に高価な場合は、予想される比較の数を調べることができます
...-comingstorm

1
あなたが述べる理由のために、全体的なパフォーマンスについて(時間的に)話すことは、あまりにも多くの詳細が考慮されるため、一般的な場合には意味がありません。選択操作のみをカウントする理由は、それらが高価であるということではなく、「ほとんどの場合」 「Landau表記(Big-Oh)の意味で、それらをカウントすると、大まかな漸近現象が得られます。定数やランタイムを考慮するとすぐに、この戦略はあまり面白くなくなります。
ラファエル

QuickSortの適切な実装は、ピボット値が必要な限りCPUレジスタに残るようにコンパイルします。これは多くの場合、同等のBig-O時間で理論的に高速なソートを打ち負かすのに十分です。
ダンライオンズ

ソートアルゴリズムが異なれば、比較の数とそれらが行う交換の数に関して異なる特性があります。また、@ DanLyonsは、ライブラリの一般的な並べ替えはユーザー指定の関数を介して比較を実行し、多くの関数呼び出しにわたってレジスタに値を保持することは非常に難しいことに注意しています。
とがった
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.