Сортировка простыми обменами, сортиро́вка пузырько́м (англ. bubble sort) — простой алгоритм сортировки. Для понимания и реализации этот алгоритм — простейший, но эффективен он лишь для небольших массивов. Сложность алгоритма: .
Алгоритм считается учебным и практически не применяется вне учебной литературы, вместо него на практике применяются более эффективные алгоритмы сортировки. В то же время метод сортировки обменами лежит в основе некоторых более совершенных алгоритмов, таких как шейкерная сортировка, пирамидальная сортировка и быстрая сортировка.
Алгоритм состоит из повторяющихся проходов по сортируемому массиву. За каждый проход элементы последовательно сравниваются попарно и, если порядок в паре неверный, выполняется обмен элементов. Проходы по массиву повторяются раз или до тех пор, пока на очередном проходе не окажется, что обмены больше не нужны, что означает — массив отсортирован. При каждом проходе алгоритма по внутреннему циклу, очередной наибольший элемент массива ставится на своё место в конце массива рядом с предыдущим «наибольшим элементом», а наименьший элемент перемещается на одну позицию к началу массива («всплывает» до нужной позиции, как пузырёк в воде — отсюда и название алгоритма).
Сложность: .
Наихудший случай:
Наилучший случай (на вход подаётся уже отсортированный массив):
Особенность данного алгоритма заключается в следующем: после первого завершения внутреннего цикла максимальный элемент массива всегда находится на -ой позиции. При втором проходе, следующий по значению максимальный элемент находится на месте. И так далее. Таким образом, на каждом следующем проходе число обрабатываемых элементов уменьшается на 1 и нет необходимости «обходить» весь массив от начала до конца каждый раз.
Так как подмассив из одного элемента не нуждается в сортировке, то для сортировки требуется делать не более итераций внешнего цикла. Поэтому в некоторых реализациях внешний цикл всегда выполняется ровно и не отслеживается, были или не были обмены на каждой итерации.
Введение индикатора (флажка F) действительно произошедших во внутреннем цикле обменов уменьшает число лишних проходов в случаях с частично отсортированными массивами на входе. Перед каждым проходом по внутреннему циклу флажок сбрасывается в 0, а после действительно произошедшего обмена устанавливается в 1. Если после выхода из внутреннего цикла флажок равен 0, то обменов не было, то есть массив отсортирован и можно досрочно выйти из программы сортировки.
Псевдокод ещё более улучшенного алгоритма с проверкой действительно произошедших обменов во внутреннем цикле.
На входе: массив , состоящий из элементов, с нумерацией от до
ЦИКЛ ДЛЯ J=1 ДО N-1 ШАГ 1 FOR J=1 TO N-1 STEP 1
F=0 F=0
ЦИКЛ ДЛЯ I=1 ДО N-J ШАГ 1 FOR I=1 TO N-J STEP 1
ЕСЛИ A[I] > A[I+1] ТО ОБМЕН A[I],A[I+1]:F=1 IF A[I]>A[I+1] THEN SWAP A[I],A[I+1]:F=1
СЛЕДУЮЩЕЕ I NEXT I
ЕСЛИ F=0 ТО ВЫХОД ИЗ ЦИКЛА IF F=0 THEN EXIT FOR
СЛЕДУЮЩЕЕ J NEXT J
В случае досрочного выхода из сортировки в этом алгоритме делается один избыточный проход без обменов.
Наихудший случай (не улучшается):
Наилучший случай (улучшается):
Время сортировки 10000 коротких целых чисел на одном и том же программно-аппаратном комплексе (операция сравнения ≈3.4мкс, обмена ≈2.3мкс) сортировкой выбором составило ≈40сек., ещё более улучшенной сортировкой пузырьком ≈30сек, а быстрой сортировкой ≈0,027сек.
больше, чем у сортировки слиянием, но при малых разница не очень большая, а программный код очень прост, поэтому вполне допустимо применение сортировки пузырьком для множества задач с массивами малой размерности на простаивающих и малозагруженных машинах.
Алгоритм можно немного улучшить, сделав следующее:
В сортировке пузырьком, при каждом проходе по внутреннему циклу, можно добавить определение очередного минимального элемента и помещение его в начало массива, то есть объединить алгоритмы сортировки пузырьком и сортировки выбором, при этом число проходов по внутреннему циклу сокращается вдвое, но более чем вдвое увеличивается число сравнений и добавляется один обмен после каждого прохода по внутреннему циклу.
Псевдокод объединённого алгоритма сортировки пузырьком и сортировки выбором (устойчивая реализация):
FOR J=1 TO N-1 STEP 1
F=0
MIN=J
FOR I=J TO N-J STEP 1
IF Y[I]>Y[I+1] THEN SWAP Y[I],Y[I+1]:F=1
IF Y[I]<Y[MIN] THEN MIN=I
NEXT I
IF F=0 THEN EXIT FOR
IF MIN<>J THEN SWAP Y[J],Y[MIN]
NEXT J
1 int *bubble_sort(int *array, int array_size)
2 {
3 int i = 0;
4 int buf;
5 char swap_cnt = 0;
6
7 if (array_size == 0)
8 return (0);
9 while (i < array_size)
10 {
11 if (i + 1 != array_size && array[i] > array[i + 1])
12 {
13 buf = array[i];
14 array[i] = array[i + 1];
15 array[i + 1] = buf;
16 swap_cnt = 1;
17 }
18 i++;
19 if (i == array_size && swap_cnt == 1)
20 {
21 swap_cnt = 0;
22 i = 0;
23 }
24 }
25 return (array);
26 }
Возьмём массив с числами «5 1 4 2 8» и отсортируем значения по возрастанию, используя сортировку пузырьком. Выделены те элементы, которые сравниваются на данном этапе.
Первый проход:
Второй проход:
Теперь массив полностью отсортирован, но алгоритму это неизвестно. Поэтому ему необходимо сделать полный проход и определить, что перестановок элементов не было.
Третий проход:
Теперь массив отсортирован и алгоритм может быть завершён.
Все приведённые реализации алгоритма имеют недостаток: каждый раз во внешнем цикле длина проходимого участка уменьшается на единицу, в то время как следующий проход должен идти до места последнего обмена.
Для улучшения этой статьи желательно: |
Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".
Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.
Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .