Javaのバブルソート

Javaのバブルソート

1. 前書き

この簡単な記事では、Javaの実装に焦点を当てて、バブルソートアルゴリズムについて詳しく説明します。

これは、最も簡単なソートアルゴリズムの1つです。コレクションがソートされるまで配列のthe core idea is tokeep swapping adjacent elementsの順序が正しくない場合。

データ構造を反復すると、小さなアイテムがリストの上部に「バブル」します。 したがって、この手法はバブルソートとして知られています。

ソートはスワップによって実行されるため、インプレースソートを実行すると言うことができます。

また、if two elements have same values, resulting data will have their order preserved –これにより安定したソートになります。

2. 方法論

前述したように、配列を並べ替えるには、隣接する要素を比較し、必要に応じてそれらを交換しながら、配列を反復処理します。 サイズnの配列の場合、n-1のような反復を実行します。

方法論を理解するために例を取り上げましょう。 配列を昇順で並べ替えたいと思います。

4 2 1 6 3 5

4と2を比較して、最初の反復を開始します。それらは間違いなく正しい順序ではありません。 スワップの結果は次のとおりです。

[2 4] 1 6 3 5

次に、4と1について同じことを繰り返します。

2[14] 6 3 5

最後までやり続けます:

2 1 [4 6] 3 5

2 1 4[36] 5

2 1 4 3[5 6]

ご覧のとおり、最初の反復の最後に、最後の要素が正しい場所にありました。 ここで、必要なのは、同じ手順をさらに繰り返して繰り返すことだけです。 ただし、既にソートされている要素は除外します。

2番目の反復では、最後の要素を除く配列全体を反復処理します。 同様に、3回目の反復では、最後の2つの要素を省略します。 一般に、k番目の反復では、インデックスn-k(除外)まで反復します。 n-1の反復の最後に、並べ替えられた配列を取得します。

テクニックを理解したところで、実装について詳しく見ていきましょう。

3. 実装

Java8アプローチを使用して説明したサンプル配列の並べ替えを実装しましょう。

void bubbleSort(Integer[] arr) {
    int n = arr.length;
    IntStream.range(0, n - 1)
    .flatMap(i -> IntStream.range(1, n - i))
    .forEach(j -> {
        if (arr[j - 1] > arr[j]) {
            int temp = arr[j];
            arr[j] = arr[j - 1];
            arr[j - 1] = temp;
            }
     });
}

アルゴリズムの簡単なJUnitテスト:

@Test
public void whenSortedWithBubbleSort_thenGetSortedArray() {
    Integer[] array = { 2, 1, 4, 6, 3, 5 };
    Integer[] sortedArray = { 1, 2, 3, 4, 5, 6 };
    BubbleSort bubbleSort = new BubbleSort();
    bubbleSort.bubbleSort(array);

    assertArrayEquals(array, sortedArray);
}

4. 複雑さと最適化

ご覧のとおり、for the average and the worst casethe time complexity isO(n^2)です。

さらに、the space complexityは、最悪のシナリオでもis O(1) as Bubble sort algorithm doesn’t require any extra memoryであり、並べ替えは元の配列で行われます。

解を注意深く分析すると、if no swaps are found in an iteration, we don’t need to iterate furtherであることがわかります。

前述の例の場合、2回目の反復の後、次のようになります。

1 2 3 4 5 6

3回目の反復では、隣接する要素のペアを交換する必要はありません。 したがって、残りのすべての反復をスキップできます。

並べ替えられた配列の場合、最初の反復自体でスワッピングは必要ありません。つまり、実行を停止できます。 これは最良のシナリオであり、time complexity of the algorithm is O(n)です。

それでは、最適化されたソリューションを実装しましょう。

public void optimizedBubbleSort(Integer[] arr) {
    int i = 0, n = arr.length;
    boolean swapNeeded = true;
    while (i < n - 1 && swapNeeded) {
        swapNeeded = false;
        for (int j = 1; j < n - i; j++) {
            if (arr[j - 1] > arr[j]) {
                int temp = arr[j - 1];
                arr[j - 1] = arr[j];
                arr[j] = temp;
                swapNeeded = true;
            }
        }
        if(!swapNeeded) {
            break;
        }
        i++;
    }
}

最適化されたアルゴリズムの出力を確認しましょう。

@Test
public void
  givenIntegerArray_whenSortedWithOptimizedBubbleSort_thenGetSortedArray() {
      Integer[] array = { 2, 1, 4, 6, 3, 5 };
      Integer[] sortedArray = { 1, 2, 3, 4, 5, 6 };
      BubbleSort bubbleSort = new BubbleSort();
      bubbleSort.optimizedBubbleSort(array);

      assertArrayEquals(array, sortedArray);
}

5. 結論

このチュートリアルでは、バブルソートがどのように機能するか、およびJavaでの実装について説明しました。 また、最適化の方法も確認しました。 要約すると、これはインプレースの安定したアルゴリズムであり、時間の複雑さがあります。

  • 最悪および平均の場合:O(n * n)、配列の順序が逆の場合

  • ベストケース:O(n)、配列が既に並べ替えられている場合

このアルゴリズムは、並べ替えの小さなエラーを検出できるため、コンピューターグラフィックスでよく使用されています。 たとえば、ほとんどソートされた配列では、完全にソートされた配列を取得するために、2つの要素のみを交換する必要があります。 バブルソートは、このようなエラーを修正できます(つまり、 この配列を線形時間で並べ替えます。

いつものように、このアルゴリズムを実装するためのコードはover on GitHubにあります。