В чем суть сортировки пузырьком? Какова ее сложность?

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

Название связано с аналогией: большие элементы постепенно всплывают к концу массива, как пузырьки.

Идея алгоритма

Пусть нужно отсортировать массив по возрастанию.

На каждом проходе сравниваются пары соседних элементов:

После первого полного прохода самый большой элемент окажется в конце массива.

После второго прохода второй по величине элемент окажется перед ним, и так далее.

Пример

Исходный массив:

[5, 2, 4, 1]

Первый проход:

5 и 2 меняем: [2, 5, 4, 1]
5 и 4 меняем: [2, 4, 5, 1]
5 и 1 меняем: [2, 4, 1, 5]

Число 5 оказалось в конце.

Код

function bubbleSort(values) {
  const result = [...values];

  for (let i = 0; i < result.length - 1; i++) {
    for (let j = 0; j < result.length - 1 - i; j++) {
      if (result[j] > result[j + 1]) {
        const temp = result[j];
        result[j] = result[j + 1];
        result[j + 1] = temp;
      }
    }
  }

  return result;
}
function bubbleSort(values: number[]): number[] {
  const result = [...values];

  for (let i = 0; i < result.length - 1; i++) {
    for (let j = 0; j < result.length - 1 - i; j++) {
      if (result[j] > result[j + 1]) {
        const temp = result[j];
        result[j] = result[j + 1];
        result[j + 1] = temp;
      }
    }
  }

  return result;
}
func bubbleSort(values []int) []int {
  result := append([]int(nil), values...)

  for i := 0; i < len(result)-1; i++ {
    for j := 0; j < len(result)-1-i; j++ {
      if result[j] > result[j+1] {
        result[j], result[j+1] = result[j+1], result[j]
      }
    }
  }

  return result
}
public class Example {
  static int[] bubbleSort(int[] values) {
    int[] result = java.util.Arrays.copyOf(values, values.length);

    for (int i = 0; i < result.length - 1; i++) {
      for (int j = 0; j < result.length - 1 - i; j++) {
        if (result[j] > result[j + 1]) {
          int temp = result[j];
          result[j] = result[j + 1];
          result[j + 1] = temp;
        }
      }
    }

    return result;
  }
}
def bubble_sort(values):
  result = values.copy()

  for i in range(len(result) - 1):
    for j in range(len(result) - 1 - i):
      if result[j] > result[j + 1]:
        result[j], result[j + 1] = result[j + 1], result[j]

  return result

Оптимизация

Если за проход не было ни одной перестановки, массив уже отсортирован. Тогда алгоритм можно завершить раньше.

function bubbleSortOptimized(values) {
  const result = [...values];

  for (let i = 0; i < result.length - 1; i++) {
    let swapped = false;

    for (let j = 0; j < result.length - 1 - i; j++) {
      if (result[j] > result[j + 1]) {
        const temp = result[j];
        result[j] = result[j + 1];
        result[j + 1] = temp;
        swapped = true;
      }
    }

    if (!swapped) {
      break;
    }
  }

  return result;
}
function bubbleSortOptimized(values: number[]): number[] {
  const result = [...values];

  for (let i = 0; i < result.length - 1; i++) {
    let swapped = false;

    for (let j = 0; j < result.length - 1 - i; j++) {
      if (result[j] > result[j + 1]) {
        const temp = result[j];
        result[j] = result[j + 1];
        result[j + 1] = temp;
        swapped = true;
      }
    }

    if (!swapped) {
      break;
    }
  }

  return result;
}
func bubbleSortOptimized(values []int) []int {
  result := append([]int(nil), values...)

  for i := 0; i < len(result)-1; i++ {
    swapped := false

    for j := 0; j < len(result)-1-i; j++ {
      if result[j] > result[j+1] {
        result[j], result[j+1] = result[j+1], result[j]
        swapped = true
      }
    }

    if !swapped {
      break
    }
  }

  return result
}
public class Example {
  static int[] bubbleSortOptimized(int[] values) {
    int[] result = java.util.Arrays.copyOf(values, values.length);

    for (int i = 0; i < result.length - 1; i++) {
      boolean swapped = false;

      for (int j = 0; j < result.length - 1 - i; j++) {
        if (result[j] > result[j + 1]) {
          int temp = result[j];
          result[j] = result[j + 1];
          result[j + 1] = temp;
          swapped = true;
        }
      }

      if (!swapped) {
        break;
      }
    }

    return result;
  }
}
def bubble_sort_optimized(values):
  result = values.copy()

  for i in range(len(result) - 1):
    swapped = False

    for j in range(len(result) - 1 - i):
      if result[j] > result[j + 1]:
        result[j], result[j + 1] = result[j + 1], result[j]
        swapped = True

    if not swapped:
      break

  return result

Сложность

В худшем и среднем случае сортировка пузырьком выполняет порядка n² сравнений.

Сложность:

Особенности

Преимущества:

Недостатки:

Вывод

сортировка пузырьком сравнивает соседние элементы и постепенно перемещает большие элементы к концу массива. Это простой, но неэффективный алгоритм со сложностью O(n²).

Источники

  • Семакин И.Г. Основы программирования и баз данных. Учебник. - М.: Академия, 2014. - 224 с.
  • Симонова Е.В. Структуры данных в C#. Линейные и нелинейные динамические структуры. - Лань, 2018. - 152 с.
  • Бертран Мейер. Почувствуй класс. Учимся программировать хорошо с объектами и контрактами. - М.: Национальный Открытый Университет "ИНТУИТ": БИНОМ. Лаборатория знаний, 2011. - 775 с.
  • Мэтт Вайсфельд. Объектно-ориентированное мышление. - СПб.: Питер, 2014. - 304 с.
  • Ривест Р., Штайн К., Лейзерсон Ч., Кормен Т. Алгоритмы: построение и анализ. - М.: Вильямс, 2007. - 1296 с.
  • Стивенс Род. Алгоритмы. Теория и практическое применение. - М.: Эксмо, 2017. - 544 с.
  • Рублев В.С. Основы теории алгоритмов. - 2-е издание, исправленное. - М.: Научный мир, 2008. - 128 с.
  • Гольдберг Г.Л. Основы алгоритмизации и программирования. - М.: Академия, 2012. - 384 с.
  • Лаврищева И.В. Технология программирования. - М.: Горячая линия - Телеком, 2011. - 400 с.
  • Сергеев И.С., Сухоруков А.И., Шестаков А.А. Программирование: учебник для вузов. - М.: БИНОМ. Лаборатория знаний, 2013. - 512 с.