挿入ソートと選択ソート


109

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

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


8
選択ソート用のウィキペディアには、挿入ソート用のウィキペディアと同様に、疑似コードとイラストが付属しています
G.バッハ

6
@G。バッハ-このおかげで...私は両方のページを何度も読んだことがありますが、違いがわかりません-したがって、この質問です。
eb80 2013

3
Computerphileによると、それらは同じです:youtube.com/watch
Tristan Forward

回答:


184

選択ソート:

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

挿入ソート:

リストを指定して、現在の要素を取得し、リストの適切な位置に挿入します。挿入するたびにリストを調整します。カードゲームでカードを並べるのと同じです。 挿入ソート

選択ソートの時間の複雑さは常にですがn(n - 1)/2、挿入ソートは、最悪の場合の複雑さほど時間の複雑性が高くなりますn(n - 1)/2。一般に、それよりも少ないか等しい比較が行われn(n - 1)/2ます。

出典:http : //cheetahonfire.blogspot.com/2009/05/selection-sort-vs-insertion-sort.html


2
@Nikolay-これは、すでに読んだcheetahonfire.blogspot.com/2009/05/…からコピーしただけです。矛盾する記事を読んだので、他に協奏曲はありますか
eb80 2013

5
主な違いは、選択手順です。選択ソートは、最小のものを選択し、それを最初のものと交換します。挿入ソートは、現在のものを適切な位置に挿入します
Nikolay Kostov

6
@ eb80どのような資料を読んでいるのかはわかりませんが、例がこれより具体的であるとは思いませんか?
G.バッハ

23
しかし、スワップの数はどうですか?選択は常にn(n-1)/ 2の比較を行いますが、最悪の場合、n-1回の交換のみを行います。最悪の場合、挿入はn(n-1)/ 2の比較とn(n-1)/ 2のスワップを行います。
Jason Goemaat 2015年

2
@Adornどちらも分割統治アルゴリズムではありません。
Asky McAskface 2017年

63

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

違いは、内部ループが行うことです。

  • 選択ソートでは、内側のループはソートされていない要素の上にあります。各パスは1つの要素を選択し、それをその最終的な場所(ソートされた領域の現在の端)に移動します。

  • 挿入ソートでは、内側のループの各パスがソートされた要素を反復します。ループが次のソートされていない要素を挿入するための正しい場所を見つけるまで、ソートされた要素は移動されます。

したがって、選択ソートでは、ソートされた要素は出力順に見つかり、見つかった場合はそのまま残ります。逆に、挿入ソートでは、ソートされていない要素は入力順に消費されるまでそのまま残り、ソートされた領域の要素は移動し続けます。

スワッピングに関する限り、selection sortは内部ループのパスごとに1つのスワップを行います。挿入ソートは通常、内部ループのtemp 前と同じように挿入される要素を保存し、内部ループがソートされた要素を1つ上にシフトする余地を残し、その後temp挿入ポイントにコピーします。


23

SELECTION SORT
特定の/ランダムな方法で記述された数値の配列があり、昇順で配置するとします。したがって、一度に1つの数値を取り、それらを最小のnoに置き換えます。リストで利用可能。この手順を実行することで、最終的に希望する結果が得られます。

ここに画像の説明を入力してください



INSERTION SORT
同様の想定を念頭に置いてくださいが、唯一の違いは、今回は一度に1つの数値を選択し、それを事前にソートされた部分に挿入するため、比較が減り、より効率的です。

ここに画像の説明を入力してください


YouTubeでmycodeschoolをチェックしてください。ただし、この回答は、YouTubeの2つのアルゴリズムの動画で説明されている内容を補完するものです。
JaydeepW 2018年

21

リンクされたリストの並べ替えの説明と配列の並べ替えの説明を比較しているために、混乱が生じている可能性があります。しかし、ソースを引用していなかったため、確信が持てません。

並べ替えアルゴリズムを理解する最も簡単な方法は、アルゴリズムの詳細な説明を取得することです(「この並べ替えはスワップを使用します。どこかで私はどこに言っているのではありません」)。トランプをいくつか入手します(5〜10で十分です)単純な並べ替えアルゴリズムの場合)、アルゴリズムを手動で実行します。

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

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

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


1
これは非常に役立ちます...最後の段落は、各種類のバリアントに起因する、私が持っていた混乱に行き着きます。
eb80 2013

1
リンクリストで挿入ソートを使用することは、インプレース配列を使用する場合とはまったく異なるスワップ効率であることを指摘するための+1
Gavin Achtemeier

11

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

  • 挿入ソート挿入する正しい位置に次の要素を、

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

また、選択ソートとは異なり、挿入ソートは安定しています。

私は両方を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

申し訳ありませんが、なぜか(選択ソートアルゴリズム)、data [i]が小さい場合は常にdata [i]がdata [current]と交換されます。基本/元の(?)選択ソートでは、range(i、data_size)の中で最小値を見つけ、data [i]をその最小値と交換します...これは少し異なります...
Tony Ma

4

簡単に言うと、選択ソートは最初に配列内の最小値を検索し、次にスワップを実行するのに対し、挿入ソートは値を取り、それをその後ろにある各値と比較します。値が小さい場合は交換されます。次に、同じ値が再度比較され、その値がその後ろの値よりも小さい場合は、再度スワップされます。私はそれが理にかなっていると思います!


4

要するに、

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

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


3

もう1つ試してみましょう。ほとんど並べ替えられた配列の幸運なケースで何が起こるかを考えてみましょう。

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

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

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

ところで、これはまさにヒープソートが選択ソートで改善するものです- ヒープのために最小の要素をはるかに迅速に見つけることができます


3

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

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


3

両方のアルゴリズムは通常、次のように機能します

手順1:並べ替えられていないリストから次の並べ替えられていない要素を取得する

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

ステップの1つは、1つのアルゴリズムの方が簡単で、その逆も同様です。

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

選択ソートソートされていないリストからどこかで要素を取り出し、ソートされたリストの最後の位置に配置します。次の要素を見つける必要があります(ほとんどの場合、並べ替えられていないリストの最初の位置ではなく、どこかにあります)。次に、並べ替えられたリストの最後に配置します。ステップ2は簡単です


2

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

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

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


1

基本的に、挿入ソートは一度に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

これらの2つのソートアルゴリズムの選択は、使用するデータ構造に依存します。

配列を使用している場合は、選択ソートを使用してください(なぜ、qsortを使用できるのですか?)。リンクリストを使用している場合は、挿入ソートを使用します。

それの訳は:

  • リンクリストトラバーサルは、配列よりもコストがかかります。
  • リンクリストの挿入は、配列よりもはるかに安価です。

挿入ソートは、ソートされたセグメントの中央に新しい値を挿入します。したがって、データは「プッシュバック」される必要があります。ただし、リンクリストを使用している場合は、2つのポインタをひねることで、リスト全体を効果的に押し戻しています。配列では、n-iスワップを実行して値を押し戻す必要がありますが、これは非常にコストがかかる可能性があります。

選択ソートは常に末尾に追加されるため、配列を使用する場合はこの問題は発生しません。したがって、データを「プッシュバック」する必要はありません。


0

簡単な説明は以下のようになります:

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

問題の説明:数値のリスト/配列を昇順で並べ替えて、選択ソートと挿入ソートの違いを理解します。

挿入ソート:理解しやすいように、上から下にリストが表示されます。最初の要素を最初の最小値と見なします。ここでのアイデアは、リスト/配列の各インデックスを線形にトラバースして、初期の最小値よりも小さい値を持つ他の要素がインデックスにあるかどうかを確認することです。そのような値が見つかった場合、それらのインデックスで値を交換するだけです。つまり、15がインデックス1の最小初期値であり、インデックスの線形トラバーサル中に、インデックス9の7のような小さい値に遭遇します。これで、インデックス9のこの値7は、値が15のインデックス1と交換されます。このトラバーサルでは、現在のインデックスの値と残りのインデックスの値を比較し続け、小さい方の値と交換します。これは、リスト/配列の最後から2番目のインデックスまで続きます。

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

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


0

挿入ソートは物事を交換しません。一時変数を使用する場合でも、一時変数を使用するポイントは、インデックスの値が以前のインデックスの値と比較して小さい場合、大きい値を小さい値の場所にシフトします。上書きするインデックス。次に、一時変数を使用して前のインデックスで置き換えます。例: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はスワッピング専用に使用されます。



0

両方に共通しているのは、どちらもパーティションを使用して、配列のソートされた部分とソートされていない部分を区別することです。

違いは、選択ソートでは、ソートされたパーティションに要素を追加しても、配列のソートされた部分が変更されないことが保証されることです。

その理由は、選択はソートされていないセットの最小値を検索し、ソートされたセットの最後の要素の直後に追加して、ソートされたセットを1増やすためです。

一方、挿入では、配列のソートされていない部分の最初の要素である次の要素のみが考慮されます。それはこの要素を取り、単にソートされたセットの適切な場所にそれを適合させます。

挿入ソートは、最小値を見つけるための操作を無駄にしているため、通常は常に部分的にしかソートされていない配列のより良い候補になります。

結論:

選択ソートは、ソートされていないセクションで最小要素を見つけることにより、要素を最後に徐々に追加します。

挿入ソートは、ソートされていないセクションで見つかった最初の要素を、ソートされたセクションの任意の場所に伝達します。


0

選択ソートと挿入ソートの時間の複雑さは同じですが、n(n-1)/ 2です。平均パフォーマンスの挿入ソートの方が優れています。ランダムな30000の整数で私のi5 cpuでテストしたところ、選択ソートは平均1.5秒かかりましたが、挿入ソートは平均0.6秒かかりました。


StackOverflowへようこそ。答えてくれてありがとう。ほとんどの場合、多くの人々がすでに視覚的なイラストで素晴らしい回答を提供していることがわかります。たとえば、7年前のニコライコストフは、挿入ソートの最悪の場合にのみ時間の複雑さが同じであると述べました。彼が間違っていると思われる場合は、詳細を記載して回答を拡大してください。
Maxim Sagaydachny

-1

素人の言葉で(そしておそらく問題の高レベルの理解を達成するための最も簡単な方法)

バブルの並べ替えは、一列に並んで身長順に並べ替えることに似ています。あなたはあなたが正しい場所にいるまであなたの隣の人と切り替え続けます。これは左から(または実装によっては右から)ずっと行われ、全員がソートされるまで切り替えを続けます。

ただし、セレクションソートでは、カードのハンドを配置するのと似ています。あなたはカードを見て、最小のものを取り、それを左端まで配置します。


3
彼は選択と挿入ソートの違いについて尋ねています
XuDing

-1

selection-特定のアイテム(最も低いアイテム)を選択し、それをi(反復の数)番目の要素と交換します。(つまり、最初、2番目、3番目.......)したがって、片側でソートされたリストを作成します。

挿入-最初と2番目の比較、3番目と2番目の比較、1番目と4番目の比較、3番目と2番目と最初の比較......

すべての並べ替えを比較するリンク

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