クイックソートは実際にはマージソートよりもはるかに高速であり、その理由は隠された定数であると読みました。さて、ランダム化されたクイックソートの複雑さの解決策は2nlnn = 1.39nlognです。これは、クイックソートの定数が1.39であることを意味します。しかし、マージソートはどうですか?マージソートの定数は何ですか?
これを解決できるかどうか見てみましょう!
マージソートでは、再帰の各レベルで、次のことを行います。
では、各ステップでいくつの比較が行われますか?まあ、分割ステップは比較を行いません。配列を半分に分割するだけです。ステップ2は(直接)比較を行いません。すべての比較は再帰呼び出しによって行われます。ステップ3では、サイズn/2の2つの配列があり、それらをマージする必要があります。マージアルゴリズムの各ステップで比較が行われ、配列要素が消費されるため、これには最大n回の比較が必要です。したがって、n回を超える比較を行うことはできません。
これを組み合わせると、次のような再発が発生します。
C(1) = 0
C(n) = 2C(n / 2) + n
(コメントで述べたように、線形項はより正確に(n-1)ですが、これによって全体的な結論が変わることはありません。上記の繰り返しを上限として使用します。)
これを単純化するために、n = 2を定義しましょう。k そして、この漸化式をkで書き直します。
C'(0) = 0
C'(k) = 2C'(k - 1) + 2^k
ここでの最初のいくつかの用語は、0、2、8、24、...です。これはk2のように見えますk、そして誘導によってこれを証明することができます。基本ケースとして、k = 0の場合、最初の項は0であり、k2の値はk も0です。帰納的ステップでは、クレームがいくつかのkに当てはまると仮定し、k + 1を考慮します。その場合、値は2(k 2k)+ 2k + 1 = k 2 k + 1 + 2k + 1 =(k + 1)2k + 1、したがって、クレームはk + 1に当てはまり、誘導が完了します。したがって、C '(k)の値はk2です。k。 n = 2なので k、これは、nが2の累乗であると仮定すると、行われる比較の数は次のようになることを意味します。
C(n)= n lg n
印象的なことに、これはクイックソートよりも優れています!では、なぜマージソートよりもクイックソートの方が速いのでしょうか。これは、行われた比較の数とは関係のない他の要因と関係があります。主に、クイックソートは適切に機能しますが、マージソートは適切に機能しないため、参照の局所性は、マージソートではクイックソートほど良くありません。これは非常に大きな要因であるため、キャッシュミスのコストは非常に大きいため、クイックソートは実際のマージソートよりもはるかに優れています。さらに、配列の並べ替えに必要な時間は、比較の数だけを考慮しているわけではありません。各配列要素が移動される回数などの他の要因も重要になる可能性があります。たとえば、マージソートでは、バッファリングされた要素にスペースを割り当て、要素を移動してマージできるようにしてから、配列にマージして戻す必要があります。これらの動きは私たちの分析ではカウントされませんが、間違いなく合計されます。これを、各配列要素を1回だけ移動し、元の配列内にとどまるクイックソートのパーティション分割ステップと比較してください。行われた比較の数ではなく、これらの追加の要因がアルゴリズムの実行時間を支配します。
この分析は最適な分析よりも少し精度が低くなりますが、 Wikipedia は、分析がおおよそn lg nであり、これがクイックソートの平均的な場合よりも実際に少ない比較であることを確認します。
お役に立てれば!
最悪の場合、単純な実装を想定すると、n要素を並べ替える比較の数は次のようになります。
ここで、lgnは、nの 2を底とする対数 を示します。
この結果は、 対応するウィキペディアの記事 またはドナルド・クヌースによる The Art of Computer Programming の最近の版で見つけることができます。 この答え の証明を書き留めました。
サイズk
respの2つのソートされた配列(またはリスト)をマージします。 m
は、せいぜい_k+m-1
_の比較を行い、せいぜい_min{k,m}
_を取ります。 (各比較の後、1つの値をターゲットに書き込むことができます。2つのうちの1つが使い果たされると、それ以上の比較は必要ありません。)
C(n)
を、n
要素の配列(リスト)のマージソートの最悪の場合の比較数とします。
次に、C(1) = 0
、C(2) = 1
があります。さらに、再発があります
_C(n) = C(floor(n/2)) + C(ceiling(n/2)) + (n-1)
_
簡単な誘導ショー
_C(n) <= n*log_2 n
_
一方、境界に任意に近づくことができることは簡単にわかります(_ε > 0
_ごとに、_(1-ε)*n*log_2 n
_以上の比較が必要なケースを作成できます)。したがって、マージソートの定数は1です。
マージソートはO(n log n)であり、各ステップで、「最悪の」場合(比較の数)に比較を実行します。
一方、クイックソートは最悪の場合O(n ^ 2)です。