挿入ソートアルゴリズム Java プログラム例付き

⚡ スマートサマリー

挿入ソート Java 配列のソート済みセクションを一度に1つの要素ずつ構築し、各キーが正しい位置に配置されるまで大きな値を右にずらしていくため、小規模なデータセットに最適です。

  • 🔘 定義: 挿入ソートは、1つの要素を削除し、ソート済みの部分内の正しい位置に挿入します。
  • ☑️ プロセス: 各処理では、キーを以前の値と比較し、値が大きい場合は右に1つずらします。
  • プログラム: その Java 例えば、{860, 8, 200, 9} をソートし、各比較とスワップを出力します。
  • 🧪 複雑: 最良の場合の実行時間はO(n)であり、平均的な場合と最悪の場合はO(n²)に達する。
  • 🛠️ メモリ: ソートはインプレースで行われるため、補助メモリは配列のサイズに関係なくO(1)のままです。
  • 📊 行動: このアルゴリズムは安定していて適応性も高いため、ほぼソート済みの配列はごくわずかなシフトで処理が完了します。

挿入ソートアルゴリズム Java

挿入ソートアルゴリズムとは何ですか?

挿入ソートは、小さなデータセットに適したシンプルなソートアルゴリズムです。 各反復中に、アルゴリズムは次のことを行います。

  • 配列から要素を削除します。
  • 最大値と比較します 配列.
  • 要素を正しい位置に移動します。

この動作は、カードゲームでプレイヤーが手札を並べる方法に似ています。新しいカードは1枚ずつ手に取られ、より大きなカードを追い越して左に押し出され、適切な位置に収まるまで移動されます。すべての移動は元の配列内で行われるため、挿入ソートはインプレースかつ安定しています。

初心者向けの同じファミリーに属します Java ソートルーチンとして バブルソートしかし、既に部分的に順序付けられているデータに対しては、通常は書き込み回数がはるかに少なくなります。

挿入ソートアルゴリズムプロセス

挿入ソート アルゴリズム プロセスがどのように動作するかを図で示します。

アニメの trac挿入ソートアルゴリズムのe、ソートされていないリストの並べ替え
挿入ソートアルゴリズムプロセス

アニメーションは同じ3つのステップを繰り返します Java 以下のプログラムが実行されます。ドライランテーブル tracプログラムが実行時に出力する手順とまったく同じように、サンプル配列 {860, 8, 200, 9} に対してこれらの手順を実行します。

合格 重要な要素 比較が行われた パス後の配列
1 8 8対860 8 860 200 9
2 200 200対860 8 200 860 9
3 9 9対860、そして9対200 8 9 200 860

パス3では、キー9が2つのより大きな値を通過する必要があるため、2回の比較が必要になることに注意してください。したがって、比較回数は、各要素の開始順序のずれに応じて増加します。

Java 挿入ソートアルゴリズムを使用して配列をソートするプログラム例:

以下のプログラムは配列 {860, 8, 200, 9} をソートし、実行中の解説を出力するので、すべての比較とすべてのシフトが確認できます。 InsertionSortExample.java そして、JDK 8以降のリリースでコンパイルしてください。

package com.guru99;
 
public class InsertionSortExample {
 
	
    public static void main(String a[])
    {    
        int[] myArray  = {860,8,200,9};  
        
        System.out.println("Before Insertion Sort");  
        
        printArray(myArray);
            
        insertionSort(myArray);//sorting array using insertion sort    
           
        System.out.println("After Insertion Sort");  
        
        printArray(myArray);   
    }    
 public static void insertionSort(int arr[]) 
	{  
        int n = arr.length;  
        
        for (int i = 1; i < n; i++)
        {   System.out.println("Sort Pass Number "+(i));
            int key = arr[i];  
            int j = i-1;  
            
            while ( (j > -1) && ( arr [j] > key ) ) 
            {  
            System.out.println("Comparing "+ key  + " and " + arr [j]); 
                arr [j+1] = arr [j];  
                j--;  
            }  
            arr[j+1] = key; 
            System.out.println("Swapping Elements: New Array After Swap");
            printArray(arr);
        }  
    }
 static void printArray(int[] array){
	    
	    for(int i=0; i < array.length; i++)
		{  
			System.out.print(array[i] + " ");  
		} 
	    System.out.println();
	    
	}
}

クラスを実行すると、 trace はここに示されています。 ソートパス番号 各行は外側のループの1回の反復を示し、各スワップの後に表示される行は、その時点での配列の状態を示します。

Code 出力:

Before Insertion Sort
860 8 200 9 
Sort Pass Number 1
Comparing 8 and 860
Swapping Elements: New Array After Swap
8 860 200 9 
Sort Pass Number 2
Comparing 200 and 860
Swapping Elements: New Array After Swap
8 200 860 9 
Sort Pass Number 3
Comparing 9 and 860
Comparing 9 and 200
Swapping Elements: New Array After Swap
8 9 200 860 
After Insertion Sort
8 9 200 860

挿入ソートの時間計算量と空間計算量

挿入ソートのパフォーマンスは、入力データが既にどれだけ順序付けられているかに大きく依存するため、最良の場合と最悪の場合では、成長率が1桁も異なるのです。

事例 入力条件 時間の複雑さ
おすすめ! 配列は既にソートされているため、内側のwhileループは実行されません。 O(N)
平均 要素はランダムな順序で到着します O(n²)
最悪 配列は逆順にソートされているため、すべてのキーが先頭に移動します。 O(n²)

スペースの使い方ははるかにシンプルです。カウンターだけ i, j, n (NAIST) と key が作成され、配列はインプレースで再配置されるため、入力がどれだけ大きくなっても補助スペースはO(1)になります。

挿入ソートは、より小さい値に到達するとすぐに内側のループが停止するため、適応型であると言えます。つまり、入力がソートされた順序に近づくほど、実行時間は線形に近づきます。

挿入ソートの利点と欠点

挿入ソートは、平均計算量が2乗になるケースがあるにもかかわらず、定数係数が非常に小さく、動作が予測可能であるため、実用ライブラリで依然として広く利用されている。

優位性

  • 書きやすく、 trac手書きなので、教育やインタビューに適しています。
  • 安定しているため、同じキーを共有するレコードは元の相対的な順序を維持します。
  • インプレース方式なので、入力配列以外にO(1)の追加メモリしか必要としません。
  • 適応型で、既にほぼソート済みのデータに対してO(n)の計算量を達成する。
  • オンラインであるため、新しい要素が到着している間でもリストを並べ替えることができます。

デメリット

  • ランダム入力や逆順入力の場合、処理時間が2乗に比例するため、大規模な配列には適さない。
  • 各シフトは配列に書き込むため、選択ソートよりも多くのデータを移動します。
  • 入力要素が数十個を超えると、マージソートやクイックソートの方がはるかに優れた性能を発揮する。

実用的なルールとしては、配列が小さい場合、データがほぼ順序通りになっている場合、または分割統治法によるソートでパーティションが少数の要素にまで縮小された場合に、挿入ソートを使用するのが良いでしょう。

挿入ソート対 Bubblソートと選択ソートの比較

これら3つのアルゴリズムはすべて二次比較ソートですが、安定性、順序付き入力への反応、および書き込み回数において違いがあります。

基準 挿入ソート Bubble 並べ替え 選択ソート
最良の場合 O(N) 早期終了フラグ付きでO(n) O(n²)
平均および最悪の場合 O(n²) O(n²) O(n²)
余分なスペース O(1) O(1) O(1)
安定した はい はい いいえ、標準配列バージョンでは
適応 はい はい、フラグ最適化が使用されている場合 いいえ
配列に書き込みます シフトは多いが、順序付けられたデータに基づくものは少ない 多くのスワップ ちょうどn-1回のスワップ

選択ソートは書き込みコストが高い場合に最も勝る。なぜなら、スワップ回数が最も少ないからである。挿入ソートは、この規模ではほぼあらゆる場面で勝る。特に部分的に順序付けられたデータの場合、ライブラリソートが優れている。これが、ライブラリソートが使用される理由である。 一般的な Java 演習 そして、JDKの内部では、非常に小さなパーティションの場合にそれに切り替わります。

よくあるご質問

最初の要素だけでも、長さ1のソート済み部分配列になっています。インデックス1から開始することで、ループは常に比較対象を持つことができるため、位置iのキーが左側の順序付きブロックに挿入されます。

AIアシスタントは、ドライランを1行ずつ読み上げたり、追加のテスト配列を生成したり、ソースコードからビッグオー記法による成長率を推定したりできます。この説明は学習補助として利用し、引用する前に教科書と照らし合わせて複雑性に関する主張を確認してください。

Yes. GitHubコパイロット メソッドのシグネチャまたはコメントから、標準的な挿入ソートを実行します。 Rev境界条件はご自身で確認してください。生成されたループでは、周囲のコードと矛盾して j >= 0 または j > -1 が使用される場合があります。

バイナリ挿入ソートは、線形走査ではなくバイナリサーチによって挿入位置を特定するため、要素ごとの比較回数をO(n)からO(log n)に削減します。シフト処理自体は変わらないため、全体の時間計算量はO(n²)のままです。

はい。再帰的なバージョンでは、最初の n-1 個の要素をソートし、最後にソートされた要素をそのプレフィックスに挿入します。これは反復処理と同じ時間計算量になりますが、O(n) のスタック領域を追加するため、実際にはループ処理の方が好まれます。

部分的にはそうです。プリミティブ型に使用されるデュアルピボットクイックソートは、非常に小さなパーティションでは挿入型ソートにフォールバックし、オブジェクトに使用されるTimSortは、短い連続した要素をバイナリ挿入ソートでソートしてからマージします。

よくある間違いは、外側のループを0から開始すること、arr[j] = keyと書く代わりにarr[j+1] = keyと書くこと、そしてj > -1ガードを省略することです。このガードを省略すると、キーが位置0にあるべき場合にArrayIndexOutOfBoundsExceptionが発生します。

はい。Comparable型の場合は「より大きい」テストをcompareToに、それ以外の場合はComparator呼び出しに置き換えてください。シフトロジックは変更されず、安定性が維持されます。これは、オブジェクトが同じソートキーを共有する場合に重要です。