web-dev-qa-db-ja.com

クイックソートとマージソート

なぜクイックソートはマージソートよりも優れているのでしょうか?

104
Ganesh M

ウィキペディアのクイックソート を参照してください:

通常、クイックソートは実際には他のΘ(nlogn)アルゴリズムよりもはるかに高速です。これは、その内部ループをほとんどのアーキテクチャで効率的に実装できるためです。時間。

非常に低いメモリ要件も大きなプラスであることに注意してください。

110
Benoît

通常、クイックソートは、データがメモリに格納されている場合、マージソートよりも高速です。ただし、データセットが巨大で、ハードドライブなどの外部デバイスに格納されている場合、マージソートが速度の面で明確な勝者です。外部ドライブの高価な読み取りを最小限に抑え、並列計算にも適しています。

72
Michael

マージソートの最悪の場合はO(n*log(n))、クイックソートの場合:O(n2)。他の場合(平均、最高)には両方ともO(n*log(n))があります。ただし、クイックソートはスペース定数であり、Mergeソートはソートする構造に依存します。

この比較 を参照してください。

また、それを見ることができます visually

61
Marcin Gil

個人的には、クイックソートとマージソートの違いを自分でテストしたいと思い、1,000,000要素のサンプルの実行時間を見ました。

クイックソートは156ミリ秒で実行できました 一方、 マージソートは247ミリ秒で実行しました

ただし、クイックソートデータはランダムであり、データがランダムであればクイックソートはうまく機能します。マージソートの場合とは異なり、マージソートはデータがソートされるかどうかに関係なく同じように実行されます。ただし、マージソートには1つの完全な追加スペースが必要で、クイックソートはインプレースソートではありません。

私も彼らのための包括的な作業プログラムを書きました。

11
bragboy

多くの場合、クイックソートがマージソートよりも優れた選択肢ですが、マージソートが論理的に優れた選択肢である場合があります。最も明らかなのは、アルゴリズムがO(n ^ 2)よりも速く実行されることが非常に重要な場合です。クイックソートは通常これよりも高速ですが、理論的に考えられる最悪の入力を考えると、O(n ^ 2)で実行される可能性があり、これは最悪のマージソートよりも悪いです。

また、クイックソートはマージソートよりも複雑です。特に、非常に堅実な実装を作成する場合は、したがって、シンプルさと保守性を目指している場合、マージソートはパフォーマンスの低下がほとんどない有望な代替手段になります。

11

クイックソートが配置されています。パーティショニング機能中にデータの位置を交換するだけです。 Mergesortでは、さらに多くのデータのコピーが必要です。 Merge関数用に別の一時ストレージ(通常は元のデータ配列と同じサイズ)が必要です。

6
Peter Leong

他に加えて:マージソートは、リンクリストのような不変のデータ構造に対して非常に効率的であるため、(純粋に)関数型プログラミング言語に適しています。

実装が不十分なクイックソートは、 セキュリティリスク になります。

6
Dario

クイックソートは、理由によりそう呼ばれます

ハイライト:両方とも安定したソートであるため(単に実装に迷惑をかける)

こいつが「乱用」されているという大げさな表記法と非常に混同されており、両方とも0(nlogn)の平均的なケースの複雑さを持っています。

しかし、マージソートは常に0(nlogn)であるのに対し、不良パーティション、つまり1要素-10要素(ソートリストまたは逆ソートリストにより発生する可能性がある)のようなスキューパーティションのクイックソートは0(n ^ 2)..

..したがって、ランダムなクイックソートがあり、ピボットをランダムに選択し、そのような歪んだパーティション化を回避し、3-4のような適度に歪んだパーティション化であってもn ^ 2シナリオ全体を無効にします。nlog(7/4)n 、理想的には1-1分割、つまりO(nlog(2)n)の2分割が必要です。

したがって、それはO(nlogn)であり、ほとんどの場合、マージソートとは異なり、「big-oh」表記の下に隠された定数は、マージソートよりもクイックソートの方が優れており、マージソートのような余分なスペースを使いません。

ただし、クイックソートを完全に実行するには、微調整、言い換え、クイックソートが必要です。

3
idexi

答えは、プリミティブ値のDualPivotQuickSortでもたらされた変更に対するクイックソートw.r.tに向かってわずかに傾くでしょう。 Java 7で使用してJava.util.Arraysでソートします

It is proved that for the Dual-Pivot Quicksort the average number of
comparisons is 2*n*ln(n), the average number of swaps is 0.8*n*ln(n),
whereas classical Quicksort algorithm has 2*n*ln(n) and 1*n*ln(n)
respectively. Full mathematical proof see in attached proof.txt
and proof_add.txt files. Theoretical results are also confirmed
by experimental counting of the operations.

Java7の実装はここにあります- http://grepcode.com/file/repository.grepcode.com/Java/root/jdk/openjdk/7-b147/Java/util/Arrays.Java

DualPivotQuickSortのさらに素晴らしい読書- http://permalink.gmane.org/gmane.comp.Java.openjdk.core-libs.devel/2628

3
appbootup

クイックソートの方が優れているとは限りません。また、それはあなたが意味するもの、メモリ消費、または速度に依存します。

メモリ消費に関しては、最悪の場合、クイックソートはn ^ 2メモリを使用できます(つまり、各パーティションは1〜n-1です)が、マージソートはnlognを使用します。

上記は速度の点で従います。

2
Jason

クイックソートが配置されています。追加メモリはほとんど必要ありません。これは非常に重要です。

中央値の適切な選択により、さらに効率的になりますが、中央値の不適切な選択でもシータ(nlogn)が保証されます。

0
DarthVader