では 各ソートの「ステップ毎に配列を表示」する完全な Java コード を用意しした。
- 同じ初期配列をコピーして使うので、アルゴリズムごとの変化を比較できます。
- 各重要な操作(比較・交換・パーティション完了など)で配列を表示します。
- 初学者が「どの要素が比べられている/交換されているか」を追いやすいように、表示は分かりやすくしています。
以下をそのまま SortVisualizer.java として保存して javac → java で実行してください。
import java.util.Arrays;
public class SortVisualizer {
// ヘルパー: 配列を見やすく表示(ステップ説明付き)
private static void printStep(String tag, int[] arr) {
System.out.println(tag + " : " + Arrays.toString(arr));
}
// バブルソートをステップ可視化
public static void bubbleSortVisual(int[] arr) {
System.out.println("\n=== Bubble Sort (Visualization) ===");
printStep("start", arr);
int n = arr.length;
int step = 1;
for (int i = 0; i < n - 1; i++) {
boolean swapped = false;
for (int j = 0; j < n - 1 - i; j++) {
System.out.println("compare (idx " + j + "," + (j+1) + "): " + arr[j] + " ? " + arr[j+1]);
if (arr[j] > arr[j + 1]) {
// swap
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
System.out.println(" swap -> step " + (step++) );
printStep(" arr", arr);
swapped = true;
}
}
if (!swapped) {
System.out.println("no swaps in this pass -> already sorted");
break;
}
System.out.println("end of pass " + (i+1));
}
printStep("result", arr);
}
// 選択ソートをステップ可視化
public static void selectionSortVisual(int[] arr) {
System.out.println("\n=== Selection Sort (Visualization) ===");
printStep("start", arr);
int n = arr.length;
int step = 1;
for (int i = 0; i < n - 1; i++) {
int minIdx = i;
System.out.println("\nselect position " + i + " (find min from idx " + i + " to " + (n-1) + ")");
for (int j = i + 1; j < n; j++) {
System.out.println(" compare idx " + minIdx + "(" + arr[minIdx] + ") with idx " + j + "(" + arr[j] + ")");
if (arr[j] < arr[minIdx]) {
minIdx = j;
System.out.println(" new min at idx " + minIdx + " (" + arr[minIdx] + ")");
}
}
if (minIdx != i) {
System.out.println(" swap idx " + i + " and idx " + minIdx + " -> step " + (step++));
int tmp = arr[i];
arr[i] = arr[minIdx];
arr[minIdx] = tmp;
printStep(" arr", arr);
} else {
System.out.println(" no swap needed for position " + i);
}
}
printStep("result", arr);
}
// クイックソート(可視化) — partition のたびに表示、swap のたびに表示
public static void quickSortVisual(int[] arr) {
System.out.println("\n=== Quick Sort (Visualization) ===");
printStep("start", arr);
quickSortHelper(arr, 0, arr.length - 1, 1);
printStep("result", arr);
}
// quickSort の再帰ヘルパ(返り値は次のステップ番号)
private static int quickSortHelper(int[] arr, int lo, int hi, int stepStart) {
if (lo >= hi) return stepStart;
System.out.println("\nquickSort range [" + lo + "," + hi + "], current: " + Arrays.toString(Arrays.copyOfRange(arr, lo, hi+1)));
int pivotIndex = partitionVisual(arr, lo, hi, stepStart);
int nextStep = pivotIndex >= 0 ? pivotIndex : stepStart;
// pivotIndex を partitionVisual が最後に出力した step の番号(返却)として使うのではなく、
// partition 内で標準出力しているので、ここでは再帰だけ行う。
quickSortHelper(arr, lo, (lo + hi) / 2, nextStep); // 左側を処理(単純に範囲を分けるイメージ)
quickSortHelper(arr, ((lo + hi) / 2) + 1, hi, nextStep);
return nextStep;
}
// シンプルな partition 可視化(ここでは Lomuto 風の分割を段階的に表示)
private static int partitionVisual(int[] arr, int lo, int hi, int stepStart) {
int pivot = arr[hi]; // 右端を pivot にする(分かりやすさ重視)
System.out.println(" partition with pivot arr[" + hi + "]=" + pivot);
int i = lo - 1;
int step = stepStart;
for (int j = lo; j <= hi - 1; j++) {
System.out.println(" compare arr[" + j + "]=" + arr[j] + " with pivot " + pivot);
if (arr[j] <= pivot) {
i++;
if (i != j) {
System.out.println(" swap idx " + i + " and " + j + " -> step " + (step++));
int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
printStep(" arr", arr);
} else {
System.out.println(" no swap needed (same index " + i + ")");
}
}
}
// pivot を適切な位置に置く
if (i + 1 != hi) {
System.out.println(" place pivot by swapping idx " + (i+1) + " and " + hi + " -> step " + (step++));
int tmp = arr[i+1]; arr[i+1] = arr[hi]; arr[hi] = tmp;
printStep(" arr", arr);
} else {
System.out.println(" pivot already in correct place");
}
System.out.println(" partition done, pivot index = " + (i+1));
return step;
}
// 配列コピー(プリミティブ配列用)
private static int[] copyOf(int[] src) {
return Arrays.copyOf(src, src.length);
}
// 実行用 main(同じ初期配列で3種を比較表示)
public static void main(String[] args) {
int[] initial = {5, 3, 8, 4, 1, 7};
// バブルソート(配列をコピーして渡す)
bubbleSortVisual(copyOf(initial));
// 選択ソート
selectionSortVisual(copyOf(initial));
// クイックソート(可視化)
quickSortVisual(copyOf(initial));
}
}
Java実行するとどうなるか(出力のイメージ)
- バブルソートは「compare …」「swap -> step X」「arr: […]」を繰り返して、途中の変化が逐次見られます。
- 選択ソートは「select position i」「compare …」「new min …」「swap」などが表示されます。
- クイックソートはパーティションごとに「pivot = …」「compare …」「swap …」「pivot placed」と出力され、部分配列ごとの動きが追えます。
補足とカスタマイズ案
- 出力が多いので配列が長いと読みにくいです。学習やデバッグ用として 長さ 10 以下 程度で試すのがオススメ。
- クイックソートの再帰の範囲分割を簡略化してあります(可視化を優先)。必要なら正規の
quickSort(arr, lo, p-1)/quickSort(arr, p+1, hi)に合わせて出力をもっと厳密に変えます。 - 視覚化をもっと豪華にしたければ(色付きターミナル、アニメーション、遅延表示など)、別途ライブラリや
Thread.sleep(...)を使って実装できます(希望があれば作ります)。
