web-dev-qa-db-ja.com

挿入ソートと選択ソート

挿入ソートと選択ソートの違いを理解しようとしています。

どちらにも、未ソートリストとソート済みリストの2つのコンポーネントがあるようです。どちらも、ソートされていないリストから1つの要素を取得し、適切な場所でソートされたリストに入れるようです。挿入ソートが正しい場所を見つけて挿入するだけで、選択ソートは一度に1つずつ交換することでこれを行うと言っているサイト/ブックを見てきました。しかし、私は他の記事が何かを言っているのを見て、挿入ソートもスワップすると言っています。その結果、私は混乱しています。正規のソースはありますか?

90
eb80

選択ソート:

リストを指定して、現在の要素を取得し、現在の要素の右側にある最小の要素と交換します。 Selection Sort

挿入ソート:

リストが与えられたら、現在の要素を取得してリストの適切な位置に挿入し、挿入するたびにリストを調整します。カードゲームでカードを配置するのに似ています。 Insertion Sort

選択ソートの時間の複雑さは常にn(n - 1)/2ですが、最悪の場合の複雑さはn(n - 1)/2であるため、挿入ソートの時間の複雑さは優れています。一般に、n(n - 1)/2よりも少ないか等しい比較が必要です。

ソース: http://cheetahonfire.blogspot.com/2009/05/selection-sort-vs-insertion-sort.html

159
Nikolay Kostov

挿入ソートと選択ソートの両方に、外側のループ(すべてのインデックスに対する)と内側のループ(インデックスのサブセットに対する)があります。内側のループの各パスは、未ソートの要素がなくなるまで、未ソートの領域を犠牲にして、ソートされた領域を1つの要素だけ拡張します。

違いは、内側のループの機能です。

  • 選択ソートでは、内側のループが未ソート要素を超えています。各パスは1つの要素を選択し、その要素を最終位置(ソートされた領域の現在の端)に移動します。

  • 挿入ソートでは、内部ループの各パスがsorted要素を反復処理します。並べ替えられた要素は、ループが次の並べ替えられていない要素を挿入する正しい場所を見つけるまで移動されます。

したがって、選択ソートでは、ソートされた要素は出力順に検出され、検出された後はそのままになります。逆に、挿入ソートでは、nsorted要素は入力順に消費されるまで配置されたままになりますが、ソートされた領域の要素は動き続けます。

スワッピングに関する限り、選択ソートは内部ループのパスごとに1回スワップします。通常、挿入ソートでは、挿入する要素をtempbefore内側のループとして保存し、内側のループにソートされた要素を1つ上にシフトする余地を残し、その後tempを挿入ポイントにコピーします。

51
comingstorm

混乱の原因は、リンクリストの並べ替えの説明と配列の並べ替えの説明を比較していることが考えられます。しかし、あなたはあなたのソースを引用しなかったので、私は確信できません。

ソートアルゴリズムを理解する最も簡単な方法は、多くの場合、アルゴリズムの詳細な説明を取得することです(「このソートはスワップを使用します。どこか。私はどこで言っていません」)。単純なソートアルゴリズムの場合)、アルゴリズムを手動で実行します.

選択ソート:ソートされていないデータをスキャンして残りの最小要素を探し、ソートされたデータの直後の位置にスワップします。完了するまで繰り返します。リストを並べ替える場合は、最小の要素を所定の位置にスワップする必要はありません。代わりに、リストノードを古い位置から削除して新しい位置に挿入できます。

挿入ソート:ソートされたデータの直後の要素を取得し、ソートされたデータをスキャンして配置する場所を見つけ、そこに配置します。完了するまで繰り返します。

挿入ソートcan「スキャン」フェーズでスワップを使用しますが、使用する必要はなく、次のようなデータ型の配列をソートしない限り、最も効率的な方法ではありません:(a)移動できない、コピーまたはスワップのみ。 (b)スワップよりもコピーの方が費用がかかります。挿入ソートがスワップを使用する場合、それが機能する方法は、場所を同時に検索することですand新しい要素をその直前の要素と繰り返し交換することにより、それより前の要素がそれより大きい。大きくない要素に到達すると、正しい場所が見つかり、次の新しい要素に進みます。

19
Steve Jessop

選択ソート
特定の/ランダムな方法で書かれた数字の配列があり、昇順で並べるとしましょう。したがって、一度に1つの数字を取り、最小の数字に置き換えます。リストで利用可能。この手順を実行すると、最終的に目的の結果が得られます。

enter image description here



挿入ソート
同様の仮定を念頭に置いてください。唯一の違いは、今回は一度に1つの数字を選択し、事前に並べ替えられた部分に挿入することです。

enter image description here

13
Akash sharma

両方のアルゴリズムのロジックは非常に似ています。両方とも、配列の先頭に部分的にソートされたサブ配列があります。唯一の違いは、ソートされた配列に配置される次の要素を検索する方法です。

  • 挿入ソートinserts正しい位置にある次の要素。

  • 選択ソートselects最小要素を選択し、現在のアイテムと交換します。

また、挿入ソートは、選択ソートとは対照的に安定しています。

私は両方をPythonで実装しましたが、それらがどれほど似ているかに注目する価値があります:

def insertion(data):
    data_size = len(data)
    current = 1
    while current < data_size:
        for i in range(current):
            if data[current] < data[i]:
                temp = data[i]
                data[i] = data[current]
                data[current] = temp

        current += 1

    return data

小さな変更により、選択ソートアルゴリズムを作成することができます。

def selection(data):
    data_size = len(data)
    current = 0
    while current < data_size:
        for i in range(current, data_size):
            if data[i] < data[current]:
                temp = data[i]
                data[i] = data[current]
                data[current] = temp

        current += 1

    return data
9
thyago stall

要するに、

選択ソート:未ソート配列から最初の要素を選択し、残りの未ソート要素と比較します。これはバブルソートに似ていますが、小さな要素をそれぞれ交換する代わりに、更新された最小の要素インデックスを保持し、各ループの終わりに交換します

挿入ソート:選択ソートの反対で、ソートされていないサブ配列から最初の要素を選択し、ソートされたサブ配列と比較し、見つかった最小要素を挿入します並べ替えられたすべての要素を右から最初の並べ替えられていない要素にシフトします。

4
Ravi

簡単に言えば、選択ソートは最初に配列内の最小値を検索し、次にスワップを実行しますが、挿入ソートは値を取得し、それを残された各値と比較します。値が小さい場合、スワップします。次に、同じ値が再度比較され、その値よりも小さい場合は再びスワップされます。それが理にかなっていることを願っています!

4
Muath

もう一度試してみましょう。ほとんどソートされた配列のラッキーなケースで何が起こるか考えてみましょう。

ソート中、配列は2つの部分を持つと考えることができます。左側-ソート済み、右側-ソートなし。

挿入ソート-ソートされていない最初の要素を選択し、すでにソートされている部分の中からその場所を見つけようとします。右から左に検索するため、比較している最初のソートされた要素(最も大きいもの、左部分の最も右側)が選択された要素よりも小さいことが非常によく起こり、次のソートされていない要素をすぐに続行できます。

選択ソート-最初の未ソート要素を選択し、未ソート部分全体の最小要素を見つけようとし、必要に応じてこれら2つを交換します。問題は、適切な部分がソートされていないため、選択した要素よりも小さい要素があるかどうかを確実に判断できないため、毎回すべての要素を検討する必要があることです。

ちなみに、これはまさに heapsort が選択ソートを改善するものです。 heap により、最小の要素をより迅速に見つけることができます。

3
Ecir Hana

選択ソート:ソートされたサブリストの作成を開始すると、アルゴリズムは、ソートされたサブリストがそれ自体の要素だけでなく、完全な配列、つまりソートされたサブリストとソートされていないサブリストの両方に関して常に完全にソートされるようにします。したがって、ソートされていないサブリストから見つかった新しい最小要素は、ソートされたサブリストの最後に追加されます。

挿入ソート:アルゴリズムは再び配列を2つの部分に分割しますが、ここでは要素は2番目の部分から選択され、最初の部分の正しい位置に挿入されます。もちろん、最終パスではすべての要素が正しい並べ替えられた位置にあるにもかかわらず、最初の部分が完全な配列に関して並べ替えられることは保証されません。

3
mankadnandan

挿入ソートの内部ループは、すでにソートされた要素を通過します(選択ソートとは逆)。これにより、正しい位置が見つかったときに内部ループを中止するが可能になります。つまり、次のことを意味します。

  1. 内側のループは、平均的なケースでは要素の半分のみを通過します。
  2. 配列がほとんどソートされると、内側のループはさらに早く中止されます。
  3. 配列が既にソートされている場合、内側のループはすぐに中止され、この場合、挿入ソートの複雑さが線形になります。

選択ソートは、常にすべての内部ループ要素を通過する必要があります。そのため、挿入ソートが選択ソートよりも優先される理由です。ただし、一方で、選択ソートでは要素のスワップがはるかに少なくなり、場合によってはより重要になります。

2
Danila Piatov

両方のアルゴリズムは一般にこのように機能します

ステップ1:ソートされていないリストから次のソートされていない要素を取得します

ステップ2:ソートされたリストの適切な場所に配置します。

1つのアルゴリズムでは手順の1つが簡単で、その逆も簡単です。

挿入ソート:ソートされていないリストの最初の要素を取得し、ソートされたリストに入れますsomewhere。次の要素(ソートされていないリストの最初の位置)を取得する場所はわかっていますが、それをどこに配置するかを見つけるには多少の作業が必要です(somewhere) 。ステップ1は簡単です。

選択ソート:ソートされていないリストから要素somewhereを取得し、ソートされたリストの最後の位置に配置します。次の要素を見つける必要があります(ソートされていないリストの最初の位置ではなく、somewhere)。ソートされたリストの最後。ステップ2は簡単です

2
my an lien

基本的に挿入ソートは、一度に2つの要素を比較することで機能し、選択ソートは配列全体から最小の要素を選択してソートします。

概念的に挿入ソートは、配列全体がソートされるまで2つの要素を比較することによりサブリストのソートを続けます。選択ソートは最小要素を選択し、2番目の最小要素を2番目の位置に切り替えます。

挿入ソートは次のように表示できます。

    for(i=1;i<n;i++)
        for(j=i;j>0;j--)
            if(arr[j]<arr[j-1])
                temp=arr[j];
                arr[j]=arr[j-1];
                arr[j-1]=temp;

選択ソートは次のように表示できます。

    for(i=0;i<n;i++)
        min=i;
        for(j=i+1;j<n;j++)
        if(arr[j]<arr[min])
        min=j;
        temp=arr[i];
        arr[i]=arr[min];
        arr[min]=temp;
1
Pankti

簡単な説明は次のとおりです。

Given:ソートされていない配列または数値のリスト。

問題ステートメント:選択ソートと挿入ソートの違いを理解するために、数値のリスト/配列を昇順でソートします。

Insertion Sort:理解を容易にするためにリストを上から下に表示します。最初の要素を初期最小値と見なします。ここでの考え方は、リスト/配列の各インデックスを直線的に横断して、初期最小値よりも小さい値を持つインデックスに他の要素があるかどうかを調べることです。このような値が見つかった場合、インデックスの値を交換します。つまり、インデックス1で15が最小の初期値であり、インデックスの線形トラバース中に、インデックス9で7などの値の小さい数値が見つかったとします。ここで、インデックス9のこの値7は、値として15を持つインデックス1と交換されます。このトラバーサルは、現在のインデックスの値と残りのインデックスとの比較を続けて、より小さい値に交換します。これはリスト/配列の最後から2番目のインデックスまで続きます。これは、最後のインデックスが既にソートされており、配列/リストの外側で確認する値がないためです。

選択ソート:リスト/配列の最初のインデックス要素がソートされていると仮定しましょう。次に、2番目のインデックスの要素から、以前のインデックスと比較して、値が小さいかどうかを確認します。トラバースは、ソート済みと未ソートの2つの部分に視覚化できます。リスト/配列内の特定のインデックスのソートされていないものからソートされたものへの比較チェックを視覚化することです。インデックス1に値19、インデックス3に値10があるとします。ソートされていないものからソートされたもの、つまり右から左へのトラバースを検討します。したがって、インデックス3で並べ替える必要があるとします。右から左に比較すると、インデックス1よりも小さい値であることがわかります。識別したら、インデックス3のこの番号10を、値19を持つインデックス1の場所に配置します。インデックス1の元の値19は、1つ右にシフトします。この走査は、リスト/配列内のすべての要素について、最後の要素まで継続します。

トラバーサルの方法の概念を理解することについての質問のように見えるので、コードを追加していません。

0
Sid

挿入ソートは物事を交換しません。一時変数を使用しますが、一時変数を使用するポイントは、インデックスの値が前のインデックスの値と比較して小さいことがわかったとき、大きい値を小さい値の場所にシフトすることです物事を上書きするインデックス。次に、前のインデックスで置換されるtemp varを使用します。例:10、20、30、50、40。反復1:10、20、30、50、50。[temp = 40]反復2:10,20、30、40(tempの値)、50。何らかの変数から目的の位置に値を挿入するだけです。

しかし、選択ソートを検討する場合、最初に低い値を持つインデックスを見つけ、その値を最初のインデックスの値と交換し、すべてのインデックスがソートされるまで繰り返しスワップし続けます。これは、従来の2つの数値の交換とまったく同じです。例:30、20、10、40、50。反復1:10、20、30、40、50。ここで、temp varはスワッピング専用に使用されます。