バブルソートの実装と効率化手法

バブルソートは、隣接要素の比較と交換を繰り返す基本的な比較ソートアルゴリズムです。そのシンプルさゆえに教育用途に広く用いられますが、実用性向上のためには複数の最適化戦略が存在します。

基本ロジック

各パス(ラウンド)で左から右へ隣接する2要素を比較し、左側が大きい場合に位置を入れ替えます。この操作により、最大値が配列末尾へ「浮かび上がる」ため、次回のパスでは末尾1要素を除外して処理できます。

実装例:標準版(O(n²))

public static void basicBubbleSort(int[] arr) {
    int n = arr.length;
    for (int round = 0; round < n - 1; round++) {
        for (int idx = 0; idx < n - 1 - round; idx++) {
            if (arr[idx] > arr[idx + 1]) {
                exchange(arr, idx, idx + 1);
            }
        }
    }
}

最適化①:早期終了判定

1ラウンド内で1度も交換が発生しなければ、配列は既に昇順であると判断し、即座に処理を終了します。

public static void earlyExitBubbleSort(int[] arr) {
    int n = arr.length;
    for (int round = 0; round < n - 1; round++) {
        boolean exchanged = false;
        for (int idx = 0; idx < n - 1 - round; idx++) {
            if (arr[idx] > arr[idx + 1]) {
                exchange(arr, idx, idx + 1);
                exchanged = true;
            }
        }
        if (!exchanged) break;
    }
}

最適化②:境界動的縮小

最後に交換が行われたインデックスを記録し、次ラウンドではその位置までしか探索しないようにします。これにより、右端の既に整列済み領域を無駄にスキャンしません。

public static void adaptiveBubbleSort(int[] arr) {
    int upperBound = arr.length - 1;
    while (upperBound > 0) {
        int lastSwapIndex = 0;
        for (int idx = 0; idx < upperBound; idx++) {
            if (arr[idx] > arr[idx + 1]) {
                exchange(arr, idx, idx + 1);
                lastSwapIndex = idx;
            }
        }
        upperBound = lastSwapIndex;
    }
}

安全な要素交換メソッド

オーバーフロー回避のため、算術演算ではなく一時変数による交換を推奨します。

public static void exchange(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

注意点:不適切な最適化のリスク

境界縮小版でlastSwapIndexの初期化を忘れると、前回の値が残り、無限ループに陥る可能性があります。特に空配列や単一要素配列のテストケースで検証が必要です。

タグ: Java sorting-algorithm bubble-sort algorithm-optimization

7月27日 21:51 投稿