クイックソートの悪い例は何ですか?


10

私はクイックソートについて学習しており、クイックソートが困難なさまざまな配列を例示したいと思います。私が念頭に置いているクイックソートには、初期ランダムシャッフルはなく、2つのパーティションがあり、中央値を計算しません。

これまでに3つの例を考えました。

[1,2,3,4,5,6,7,8,9,10] - when the array is sorted
[10,9,8,7,6,5,4,3,2,1] - when the array is reversed
[1,1,1,1,1,1,1,1,1,1] - when the array is the same values
[1,1,1,2,2,2,3,3,3,3] - when there are few and unique keys

たとえば、これについてはよくわかりません。

[1,3,5,7,9,10,8,6,4,2]

では、クイックソートが(ほぼ)理想的である配列と比較して困難な配列は何でしょうか?


2
ピボットはどのように選択されますか?あなたはそれが選択されなかった2つの方法を述べましたが、それがどのように選ばれたかではありませんでした。
Winston Ewert 2014

QuickSortの最悪のケースを教えてください-いつ発生しますか?StackOverflowで読み取り。また、sorting.atは、ソートアルゴリズムの優れた視覚化であることがわかります。

@WinstonEwertピボットは最初の要素によって選択されます。
mrQWERTY 2014

@ Renren29私は質問にに焦点を当て、それを移動しようと少し変更した理由クイックソートは、指定された配列の難しさを持っているでしょう、なぜ、むしろ例アレイを求めるよりも、(私は、人々はあなたが答えを与えることがない[2,1,2,1,2,1,2,1]とことを全体であること回答)。質問の目標は、理想的には、他の人が来て、例(数えきれないほどあります)ではなく、理由(答えがある)について詳しく知ることができるものになるでしょう。

あなたは2要素のチャンクまでクイックソートを実行していますか?実際の実装では、小さなチャンクに対してより単純なソートを使用する傾向があるためです。たとえば、N = 2の場合、比較とスワップはクイックソートよりもはるかに簡単です。
MSalters 2014

回答:


8

すべてのソートアルゴリズムには最悪のケースがあり、多くの場合、最悪のケースは本当に悪いので、テストする価値があります。問題は、基本的なアルゴリズムを知っているからといって、最悪のケースは1つもないということです。

一般的な最悪のケースは次のとおりです。逆順にソートされます。ほぼソートされた、順不同の要素。すべての値は同じです。最初(または最後)が高い(または低い)以外はすべて同じです。私たちはかつて、最悪のケースが特定の鋸歯状パターンである種類を持っていました。これは予測が非常に困難でしたが、実際には非常に一般的でした。

クイックソートの最悪のケースは、可能な限り最悪のピボットを常に選択するため、パーティションの1つに1つの要素しかありません。ピボットが最初の要素(悪い選択)の場合、既に並べ替えられたデータまたは逆に並べ替えられたデータが最悪のケースです。3つの中央値のピボットデータがすべて同じか、最初と最後だけが異なる場合、トリックは異なります。


クイックソートの場合、平均の複雑度はnlognで、最悪のケースはn ^ 2です。最悪のケースの動作をトリガーする価値があるのは、これが最大の再帰深度を生成するケースでもあるためです。単純な実装の場合、再帰の深さはnになる可能性があり、スタックオーバーフローをトリガーする可能性があります。同様の理由で、他の極端な状況(最良のケースを含む)をテストすることは価値があります。


なるほど、平均からの標準偏差が実際に分割結果を決定します。
mrQWERTY 2014

「...そして、ほとんどすべての場合、最悪のケースは本当に悪いので、それをテストする価値があります。」。それは議論の余地があります。この表を見ると、en.wikipedia.org / wiki /ほとんどの "良い"ソートアルゴリズム(つまり、平均的なO(NlogN)パフォーマンス以上)では、最悪のケースと平均的なケースは同じ複雑さであると結論付けています。これは通常、最悪のケースをテストする価値がないことを示唆しています。(テストがおそらくO(N)...またはそれより悪いと仮定してください。)
スティーブンC

@ Renren29:2つまたは3つの値が同じ場合にのみ、3つのピボットの中央値が最初または最後になります。SDは入りません。
david.pfx 2014

@StephenC:クイックソートを含む多くの「良い」アルゴリズムはn ^ 2の最悪の場合の複雑さを持っています。しかし、編集を参照してください。
david.pfx 2014

@ david.pfx-"Some" ...はい。「ほぼすべて」...いいえ。
Stephen C

0

アルゴリズムは、ランダム化されたピボットを使用して、ほとんどの悪いケースから脱出します。ピボットに等しい連続要素は、パーティション分割と非対称検索から除外されます。ピボット以上の要素を前方に検索、ピボット未満の要素を後方に検索します。
MichaelTに感謝します。非対称検索は[2,1,2,1,2,1,2,1]を解決するために考案されました。

次の結果は、関数qsort_random()によって生成されます。N = 100,000

usec    call   compare   copy    pattern
80132   62946  1971278   877143  random
47326   57578  1606067   215155  sorted : 0,1,2,3,...,n-1
49927   63578  1628883   338715  sorted in reverse : n-1,n-2,...,2,1,0
55619   63781  1596934   377330  nearly reverse : n-2,n-1,n-4,n-3,...,2,3,0,1
54714   66667  1611454   290392  median-3-killer : n-1,0,1,2,...,n-2
1491    1      99999     4       all values the same : n,n,n,...
1577    1      99999     4       first is higher : n,1,1,1,...
2778    2      156159    10      last is lower : n,n,n,...,n,1
2994    3      199996    100009  a few data : n,...,n,1,...,1
3196    3      199996    50012   zigzag : n,1,n,1,...,n,1
917796  56284  67721985  673356  valley(sawtooth?) : n-1,n-3,...,0,...,n-4,n-2

ほとんどの場合、ランダムパターンよりも高速です。谷パターンは、ほとんどのピボット選択の悪いケースです。

qsort(3)       usec = 14523   call = 0      compare = 884463    copy = 0
qsort_head()   usec = 138609  call = 99999  compare = 8120991   copy = 1214397
qsort_middle() usec = 664325  call = 99999  compare = 52928111  copy = 1036047
qsort_trad()   usec = 118122  call = 99999  compare = 6476025   copy = 1337523
qsort_random() usec = 295699  call = 58806  compare = 19439952  copy = 732962
qsort_log2()   usec = 66411   call = 63987  compare = 1597455   copy = 944821

qsort_log2()は、log2(N)要素のピボットを選択することにより、不正なケースからエスケープします。
qsort(3)は、インデックスソートのマージソートであるGNUライブラリを使用します。
qsort_trad()は、最初、中間、最後の要素でピボットを選択します。
qsort_random()とqsort_log2()はスワッピングを使用しません。
ソースCプログラムとスクリプトはgithubに投稿されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.