Пузырьковая сортировка на Java

Пузырьковая сортировка на Java

1. Вступление

В этой быстрой статье мы подробно рассмотрим алгоритм пузырьковой сортировки, сосредоточившись на реализации Java.

Это один из самых простых алгоритмов сортировки; 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 элемента. Как правило, для k-й итерации мы выполняем итерацию до индексаn-k (исключено). В конце итерацийn-1 мы получим отсортированный массив.

Теперь, когда вы понимаете технику, давайте погрузимся в ее реализацию.

3. Реализация

Давайте реализуем сортировку для примера массива, который мы обсуждали, используя подход Java 8:

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 case,the 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

В третьей итерации нам не нужно менять местами какие-либо пары соседних элементов. Таким образом, мы можем пропустить все оставшиеся итерации.

В случае отсортированного массива свопинг не потребуется в самой первой итерации, что означает, что мы можем остановить выполнение. Это лучший сценарий и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), когда массив уже отсортирован

Алгоритм популярен в компьютерной графике, благодаря его способности обнаруживать небольшие ошибки при сортировке. Например, в почти отсортированном массиве нужно поменять местами только два элемента, чтобы получить полностью отсортированный массив. Bubble Sort может исправить такие ошибки (т.е. сортировать этот массив) в линейное время.

Как всегда, код для реализации этого алгоритма можно найтиover on GitHub.