🎯
【Java】挿入ソート
挿入ソートとは
挿入ソートとは、要素を挿入しながら配列やリストをソートするアルゴリズムの1つです。
挿入ソートは、ソートアルゴリズムの中では、構造が単純であり実装が容易です。反面、計算量が多い場合や効率性が重視される場合には、効率が悪くなることがあります。
問題の内容と回答の方針等
- 問題
- サイズ
n
の数列a
を挿入ソートせよ。
- サイズ
- 条件
- 配列の最初の要素を整列済みと見なす。
- 解答方針
- 数列
a
を配列a[]
で管理します。 -
i
回目にa[i]
を、合計n-1
回挿入します。但し、i
の初期値を1
とします。 - アルゴリズムにより要素
a[i]
は消えてしまうので、要素a[i]
を変数x
に保存します。 - 変数
x
を入れる場所を探す変数j
をi-1
で初期化します。 - 変数
j
が0
以上、かつ、a[j] > x
である間、a[j]
を右にずらし、j
を1
減らすことを繰り返します。 -
a[j + 1]
に変数x
代入します。
- 数列
- 今回の入力値
上からn
、a
とする。4 8 1 3 2
挿入ソートのコード例
import java.util.*;
public class Main {
static void print(int[] a, int n) {
for (int i = 0; i < n; i++) {
if (i > 0)
System.out.print(" ");
System.out.print(a[i]);
}
System.out.println();
}
static void insertionSort(int[] a, int n) {
for (int i = 1; i < n; i++) {
// 変数xに配列の要素a[i]を保存する。
int x = a[i];
// 変数jに配列のインデックスiから1引いたものを代入する。(インデックスj=i-1番目)
int j = i - 1;
// インデックスjが0以上、かつ、要素a[j]が変数xより大きい間
while (j >= 0 && a[j] > x) {
// 要素a[j+1]に要素a[j]をコピーする。(a[j]を1つ右にずらす)
a[j + 1] = a[j];
// jを1減らす
j--;
}
// 要素a[j+1]に変数xを挿入する。
a[j + 1] = x;
print(a, n);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
insertionSort(a, n);
}
}
挿入ソートアルゴリズムの解説
挿入ソートアルゴリズムに該当する下記の部分のみを解説します。
static void insertionSort(int[] a, int n) {
for (int i = 1; i < n; i++) {
int x = a[i];
int j = i - 1;
while (j >= 0 && a[j] > x) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = x;
print(a, n);
}
}
仮引数は下記の通りです。
a = [8, 1, 3, 2]
n = 4
i = 1 の場合
-
for
文の条件式i=1 < n=4
を満たすので、 - 変数
x
に、配列の要素a[1]
の1
を代入します。 - 変数
j
に、i - 1
の0
を代入します。 -
while
文の条件式j=0 >= 0
を満たし、かつ、a[j]=8 > x=1
を満たすので、 - 要素
a[j + 1]
に要素a[j]=8
を代入します。
この時の配列aは下記の通りになります。一旦、配列の要素a = [8, 8, 3, 2]
a[1]
の1
は消えてしまいます。 - 変数
j
は-1
となるので、while
文の条件を満たさないので、このループを抜けます。 -
a[-1 + 1]
は、a[0]
となるので、これに変数x
の1
を代入します。
この時の配列aは下記の通りになります。a = [1, 8, 3, 2]
-
print
メソッドを呼び出し、実引数として配列a
と変数n
を渡します。
i = 2 の場合
-
for
文の条件式i=2 < n=4
を満たすので、 - 変数
x
に、配列の要素a[2]
の3
を代入します。 - 変数
j
に、i - 1
の1
を代入します。 -
while
文の条件式j=1 >= 0
を満たし、かつ、a[j]=8 > x=3
を満たすので、 - 要素
a[j + 1]
に要素a[j]=8
を代入します。
この時の配列aは下記の通りになります。一旦、配列の要素a = [1, 8, 8, 2]
a[2]
の3
は消えてしまいます。 - 変数
j
は0
となるので、while
文の条件j=0 >= 0
を満たしますが、a[j]=1 > x=3
を満たさないので、このループを抜けます。 -
a[0 + 1]
は、a[1]
となるので、これに変数x
の3
を代入します。
この時の配列aは下記の通りになります。a = [1, 3, 8, 2]
-
print
メソッドを呼び出し、実引数として配列a
と変数n
を渡します。
i = 3 の場合
-
for
文の条件式i=3 < n=4
を満たすので、 - 変数
x
に、配列の要素a[3]
の2
を代入します。 - 変数
j
に、i - 1
の2
を代入します。 -
while
文の条件式j=2 >= 0
を満たし、かつ、a[j]=8 > x=2
を満たすので、 - 要素
a[j + 1]
に要素a[j]=8
を代入します。
この時の配列aは下記の通りになります。一旦、配列の要素a = [1, 3, 8, 8]
a[3]
の2
は消えてしまいます。 - 変数
j
は1
となるので、while
文の条件j=1 >= 0
を満たし、かつ、a[j]=3 > x=2
を満たすので、 - 要素
a[j + 1]
に要素a[j]=3
を代入します。
この時の配列aは下記の通りになります。a = [1, 3, 3, 8]
- 変数
j
は0
となるので、while
文の条件j=0 >= 0
を満たしますが、a[j]=1 > x=3
を満たさないので、このループを抜けます。 -
a[0 + 1]
は、a[1]
となるので、これに変数x
の2
を代入します。
この時の配列aは下記の通りになります。a = [1, 2, 3, 8]
-
print
メソッドを呼び出し、実引数として配列a
と変数n
を渡します。
これで、ようやく配列a
がソートされました。
Discussion