理解を深めるために、以下で必要なプログラムに取り組んでいます。
クイックソートの最悪の場合の実行時間はどのくらいですか?また、この悪い場合のパフォーマンスの原因は何ですか?この問題を軽減するために、クイックソートプログラムをどのように変更できますか?
最悪の場合O(n^2)
があり、ピボット固有の最小または最大要素の場合に発生することを知っています。私の質問は、この問題を軽減するためにプログラムをどのように修正すればよいかです。
良いアルゴリズムが良いでしょう。
クイックソートのパフォーマンスは、ピボット選択アルゴリズムに依存しています。最も単純なピボット選択アルゴリズムは、最初の要素をピボットとして選択することです。データが既にソートされている場合、これにより最悪の場合の動作が発生することは簡単にわかります(最初の要素は常に最小値になります)。
この問題を解決するための2つの一般的なアルゴリズムがあります。ランダムにピボットを選択するか、3つの中央値を選択します。ランダムは明らかなので、詳細には触れません。 3の中央値には、3つの要素(通常は最初、中間、最後)を選択し、それらの中央値をピボットとして選択することが含まれます。
乱数ジェネレーターは通常、擬似ランダム(したがって決定論的)であり、3つのアルゴリズムの非ランダム中央値は決定論的であるため、最悪の場合の動作をもたらすデータを構築することは可能ですが、通常の使用法ではめったに起こりません。
また、パフォーマンスへの影響も考慮する必要があります。乱数ジェネレーターの実行時間は、クイックソートの実行時間に影響します。中央値が3の場合、比較の数が増えます。
最悪のパフォーマンス条件:
選択された各ピボットが「最大」または「最小」であり、このパターンが繰り返される場合
だから1 3 5 4 2
ピボットが1,2,3,4,5または5,4,3,2,1の順序で選択された場合
最悪の場合の実行時間はO(n * n)です
最悪の事態を避ける方法:
(1)配列を5つのセットに分割します。1..100の場合、セットは(1..20)(21..40)(41..60)(61 .. 80)(81..100)
(2)各セットの最初の5つの要素の中央値を選択するso(3)(23)(43)(63)(83)
(3)ここでピボットとしてそれらの中から中央値を選択しますので、ここでその(43)
簡単な変更は、ピボットをランダムに選択することです。これにより、良い結果が得られます 高い確率で 。
しばらく経ちましたが、クイックソートの最悪のケースは、データがすでにソートされていたときだと思います。データが既にソートされているかどうかを簡単に確認することで、この問題を軽減できます。
最悪の場合の実行時間は、クイックソート内のパーティション方法によって異なります。これには2つの側面があります。
ピボットを選択するための優れた戦略は、以前の投稿(中央値の中央値、または3つの中央値またはランダム化)で無視されました。しかし、ピボットが賢明に選択されていても、極端に、配列がすべて等しい要素を持っている場合、2つのパーティションのみが構築されている場合、最悪の場合のランタイムにつながります。
この問題を回避する方法は、下部(要素<ピボット)、等しい(要素=ピボット)、上部の3つのパーティションに分割することです。 「= pivot elements」は最終位置にあります。空でない場合は、下位および上位パーティションをソートする必要があります。
ランダム化、中央値の中央値、またはピボットを選択するための組み合わせを組み合わせた最悪のシナリオは非常にまれですが、不可能ではありません。これにより、アルゴリズムにO(n²)の上限が残ります。
私が疑問に思う質問はよく聞かれます。 AFAIの研究には、その最悪性の2つの鍵があります。
- 昇順または降順に関係なく配列がすでにソートされている場合に加えてリストの最小(最小)または最大(最大)としてピボットを選択要素 [2,3,4]または[4,3,2]
- すべての要素が同じ場合。 [2,2,2]