10の並べ替えアルゴリズムの接続と進行に関する考察


序文

小規模での数値の並べ替えは非常に簡単な作業であり、算数を学んだすべての友人は簡単にそれを処理できます。しかし、データスケールが特定のレベルに達すると、迅速かつ効率的に並べ替える方法が興味深い課題になります。多くの場合、データ量の多いアプリケーションシナリオでは、並べ替えアルゴリズムがその能力を最大限に発揮できます。
ここに画像の説明を挿入
次のコンテンツでは、すべての並べ替えアルゴリズムを簡単な方法で説明するために最善を尽くします。まず、次の点を明確にする必要があります。

  • すべての状況で最適なソートアルゴリズムはありません。
  • この記事では、比較基づく並べ替えについてのみ説明します。それが文字であろうと数値であろうと、比較ルールが必要です。
  • 安定性とは、並べ替えの前後で、2つの等しいデータの相対位置が変化しないことを意味します

並べ替えアルゴリズム

バブルソート

隣接する2つの要素が比較されるたびに、比較ルールに従って交換が実行され、最大または最小の要素が片側に切り替わるたびに、問題のサイズがnからn-1に変化します。
ここに画像の説明を挿入
上記のコードは比較的単純です。ここに3つの指示があります。

  1. フラグの機能は、バブルソーティングで交換があったかどうかを再度判断することで、交換がなければ注文が整い、残りのループ判断を継続する必要がなく、そのまま終了することができます。
  2. 時間の複雑さ:Best-O(N)は最初からソートされており、走査後に完了します。
    Worst-O(N ^ 2)完全な逆順、2つのネストされたループ。
  3. 利点は、リンクリスト構造に適用でき、安定していることです。

挿入ソート

ここに画像の説明を挿入
挿入ソーティングとは、カードを引く、トランプを引くというプロセスで、常に新しいカードを1枚ずつ比較して正しい位置を見つけ、挿入していきます。同様に、挿入ソートは、このテストから抽象化されたソートアルゴリズムです。
ここに画像の説明を挿入
時間の複雑さと安定性は、バブルソートと同じです。

上記の2つの並べ替えアルゴリズムを要約すると、最初に「反転ペア」の概念が与えられます。添え字i <jの場合、A [i]> A [j]の場合、(i、j)は反転ペアのペア(反転)。したがって、ソートまたは挿入ソートの選択に関係なく、逆ペアを除去する必要があり、バブルソートで隣接する要素を交換すると、逆ペアが1つ除去されるだけです。挿入ソートでは、シーケンスが基本的に順序付けられている場合、挿入ソートは単純で効率的です。重要な結論が導き出されます。並べ替えるために2つの要素のみを交換するアルゴリズムの平均時間の複雑さはΩ(N 2)\ Omega(N ^ 2)です。Ω N2、アルゴリズムを急ぐ必要があるため、各交換で複数の逆順ペアを削除する必要があります。

ヒルソート

1回の交換でより多くの反転ペアを排除したいので、この交換の2つの数の範囲を拡大して、一度に複数の反転ペアを排除することが可能になり、結果としてアルゴリズムの時間がより複雑になります。 、そして挿入ソートの単純さを保持します。ここに画像の説明を挿入
元のヒル順序は次のコードで理解できます。
ここに画像の説明を挿入
コアは、等間隔で取得されたサブシーケンスを挿入およびソートすることであり、間隔は増分シーケンスに従って1に減らされ、完全な有効性を保証できます。しかし、この時間の複雑さはまだ理想的ではありません、それをどのように改善するのですか?

インクリメンタルシーケンスを改善!

それは常に前に半分でした。改善するためのさまざまな(ファンキーなインクリメンタルシーケンス、興味がある場合は、ソースペーパーに移動できます)は次のとおりです。
ここに画像の説明を挿入

並べ替えを選択

選択ソートの疑似コードは次のとおりで、簡単に理解できます。
ここに画像の説明を挿入

ヒープソート

ここに画像の説明を挿入
コードの最後の部分は、余分なスペースの一時的な値を元の配列に割り当てることです。

マージソート

マージソートについては、コア、つまり順序付けられたサブ列のマージを把握する必要があります
ここに画像の説明を挿入
たとえば、上の図では、Aサブ列とBサブ列が大きな順序のサブ列にマージされています。各要素を1回スキャンする必要があるため、時間の複雑さはO(N)O(N )O N
コード実装のアイデアは、左と右のサブシーケンスに2つのポインターをそれぞれソートするように設定することです。小さい方を最初に結果を格納する配列に移動し、2つのサブシーケンスの1つにあるすべての要素がスキャンされるまでポインターを右に移動できます。 、別のサブシーケンスの残りの部分は、結果の配列に直接移動できます。元の配列に割り当てる最後のトリックは、右から左に割り当てることです。なぜ左から右にしないのかを考えてみてください。
擬似コードは次のとおりですここに画像の説明を挿入
。次の質問は、上記の合併のアイデアをどのように実現するかです。

  1. 最初のアルゴリズムは、分割統治+再帰アルゴリズムによって実現できると考えることは難しくありません。つまり、元の配列は、そのサブ問題に対処するために継続的に分割されます。コードは次のように実装されます。上記で作成したMerge関数が呼び出されることに注意してください。
    ここに画像の説明を挿入
    時間の複雑さは、古典的な分割統治再帰的導出から導き出すことができ、それは期待に沿った数値でなければなりません。
    ここに画像の説明を挿入
    手動で導出して、記憶を深めることができます。
    ここに画像の説明を挿入
    彼はどんな状況でもO(NlgN)で安定していることに注意してください。(なぜですか?上記のコードを検討してください。)

  2. 非再帰的アルゴリズムを実装する方法は?

アイデアは、長さの2つのサブシーケンスを毎回マージすることであり、結果シーケンスにマージされるまで、長さは1から増加します。
次の図で彼の時間の複雑さを考慮してください。
ここに画像の説明を挿入
実際、この画像はやや誤解を招くものであり、正解はO(N)O(N)です。O N 、長さNの2つの配列を開いて値を前後に割り当てるだけなので、このプロセスについて慎重に検討してください。
コードは
ここに画像の説明を挿入
の図に示すように実装されています。マージソートの外部インターフェイスは次のとおりです。


赤い配列の部分に注目してください。実際には、結果配列のスペースと一時配列のスペースを前後に使用するプロセスが実現されています。

ここに私たちは全体的な感じがあります、ああ、合併は良いです、その最悪と平均の複雑さはどちらもO(N lg N)O(NlgN)O N l g N で安定しています。これは完璧な並べ替えアルゴリズムではありませんか?しかし、これは事実ですか?ちなみに、余分なスペースが必要で、配列間を行き来する必要があるため、内部ソートでは一般的に使用されず、外部ソートで主に使用されます。

クイックソート

次に、これが最も一般的に使用されており、最速のソートアルゴリズムとして認識されています。はい、高速なソートです。クイックソートについては、対話形式でより鮮明な記事を書きました。ここに移動してください彼の考えについては下の図を参照してください。それほど複雑に感じることはありませんが、彼の実装プロセスで多くの値を選択することは非常に注意する必要があります。注意しないと、パフォーマンスが大幅に低下します。詳細については、高速に関する私の記事を参照してください記事の行。
ここに画像の説明を挿入
注意点の要約は次のとおりです。

  1. この種の高速ソートの最良のケースは、毎回中央の数値(middle)を選択することであり、時間の複雑さはO(N lg N)O(NlgN)です。O N l g N
  2. ピボットの選び方は?最初の要素をピボットとして直接選択できますか?最悪のケースは何ですか?ここに画像の説明を挿入
    予想通り、効果は爆発しました。それを改善するには?
    現在、ピボットを選択する最も一般的な方法は、最初、中間、最後の3つの数値の中央値をピボットとすることです。コードは次のとおりです(考えてみて、乱数をとってもかまいませんか)。
    ここに画像の説明を挿入
    上記のコードの最後の2行について考えると、彼の考えは、真ん中の数が右よりも小さいことを知っているので、すぐ前に直接置いて、節約できるようにしてください。最初と最後の2つの要素を比較するオーバーヘッドを削除します。
  3. サブセットを分割する方法は?

ここに画像の説明を挿入
高速ソートの原則はここでは繰り返さないが、そのコア、および挿入ソートに対する利点は、各ピボット挿入(交換)の位置が最終位置であり、移動する必要がないことです。同時に、アレイはサブセットに分割されます。
次に、詳細な質問について考えることは、面接担当者がよく詳細に検討する質問でもあります。
"並べ替えプロセス中にピボットピボットと等しい要素がある場合、どのように処理すればよいですか?" {\ color {red} "並べ替えプロセス中にピボットピボットと等しい要素がある場合、どのように処理する必要がありますか?"}ようであれば、行の順序を介してプロセス陽性ウェルがいるプライムなど要素P I V O T でなければならないようにどのように処理それを
もはや二つの選択肢よりも、この時点では、交換を停止し、又は無視します。
最初の方法では、極端な場合を考慮して、すべての数値が等しい場合、多くの無駄な比較と交換が行われますが、利点は、ピボットを途中で停止でき、時間の複雑さがO(N lg N)O(NlgN)に達する可能性があることです。O N l g N
2番目の方法では、極端な場合に無効な交換が回避されますが、時間の複雑さはO(N 2)O(N ^ 2)です。O N2。それで、えっと。最初の1つを選択する必要があります。
クイックソートの短所は、再帰を使用することです。これは、大規模なデータには十分対応できないため、スケールが十分に小さい場合、単純なソートを使用して、選択的ソートなどの問題を解決できます。
最後に、コードが与えられます:

ここに画像の説明を挿入

ここでのカットオフは、選択的ソートを使用するように設定したデータサイズのしきい値であり、赤いボックスは外部から呼び出されるインターフェイスであることに注意してください。

テーブルの並べ替え

アイデアは、データ(キー)自体を移動するのではなく、ポインター(テーブルの添え字)をソートに移動することです。これは間接的なソートです。
ここに画像の説明を挿入

バケットソート

比較サイズに基づいて要素を交換するだけで、最悪の時間の複雑さはO(N lg N)O(NlgN)O N l g N スワップ中に他のことができますか?(おばあちゃんの美の批評[笑い声])
ここに画像の説明を挿入

基本ソート

カーディナリティソートは、バケットソートの改良版です。
ここに画像の説明を挿入
Pは、lg(N)のレベルでのスキャンの数を示します。バケットの数が十分に少ない場合は、線形時間でソートできます。

総括する

説明:
選択ソートが不安定である理由は、ジャンプとスワッピングによって等しい数のシーケンスを逆にすることができるためです。簡単な例として、それが安定しているかどうかを知ることができます...例:(7)2 5 9 3 4 [7] 1 ...直接選択ソートアルゴリズムを使用してソートすると、(7)と1が交換され、(7)が[7]の後ろまで実行され、元の順序が変更されて不安定になりました。
Hillソートのdの値は、増分シーケンスの選択によって異なります。
ヒープソートとマージソートの平均と最悪はO(N lg N)O(NlgN)です。O N l g N ですが、マージの欠点は、配列を「逆さま」にするために追加の配列スペースが必要になることです。マージの利点は、安定性です。
クイックソートは不安定です(ホップアンドスワップ、繰り返しはしません)が、再帰的であるため、追加のスタックスペースが必要です。

ここに画像の説明を挿入


注:
上記のすべての画像は、浙江大学のデータ構造オープンコースウェアのppt、ソースアドレスからのものです

おすすめ

転載: blog.csdn.net/weixin_41896265/article/details/108414565