Сортировка пузырьком
Сортировка простыми обменами, сортировка пузырьком (англ. bubble sort) — один из квадратичных алгоритмов сортировки.
Алгоритм
Алгоритм состоит в повторяющихся проходах по сортируемому массиву. На каждой итерации последовательно сравниваются соседние элементы, и, если порядок в паре неверный, то элементы меняют местами. За каждый проход по массиву как минимум один элемент встает на свое место, поэтому необходимо совершить не более
проходов, где размер массива, чтобы отсортировать массив.Псевдокод
Ниже приведен псевдокод сортировки пузырьком, на вход которой подается массив
, состоящий из элементов.BubbleSort(A) for i = 0 to n - 2 for j = 0 to n - 2 if A[j] > A[j + 1] swap(A[j], A[j + 1]);
Оптимизация
- Можно заметить, что после -ой итерации внешнего цикла последних элементов уже находятся на своих местах в отсортированном порядке, поэтому нет необходимости производить их сравнения друг с другом. Следовательно, внутренний цикл можно выполнять не до , а до .
- Также заметим, что если после выполнения внутреннего цикла не произошло ни одного обмена, то массив уже отсортирован, и продолжать что-то делать бессмысленно. Поэтому внутренний цикл можно выполнять не раз, а до тех пор, пока во внутреннем цикле происходят обмены.
При использовании первой оптимизации сортировка принимает следующий вид:
BubbleSort(A) for i = 0 to n - 2 for j = 0 to n - i - 2 if A[j] > A[j + 1] swap(A[j], A[j + 1]);
Сложность
В данной сортировке выполняются всего два различных вида операции: сравнение элементов и их обмен. Поэтому время всего алгоритма
, где — время, затрачиваемое на сравнение элементов, а — время, за которое мы производим все необходимые обмены элементов.Так как в алгоритме меняться местами могут только соседние элементы, то каждый обмен уменьшает количество инверсий на единицу. Следовательно, количество обменов равно количеству инверсий в исходном массиве вне зависимости от реализации сортировки. Максимальное количество инверсий содержится в массиве, элементы которого отсортированы по убыванию. Несложно посчитать, что количество инверсий в таком массиве . Получаем, что .
В неоптимизированной реализации на каждой итерации внутреннего цикла производятся
сравнений, а так как внутренний цикл запускается также раз, то за весь алгоритм сортировки производятся сравнений.В оптимизированной версии точное количество сравнений зависит от исходного массива. Но точно известно, что их количество не меньше, чем количество обменов, и не больше, чем
— максимальное количество сравнений для данной сортировки. Следовательно, .В итоге получаем
.Пример работы алгоритма
Возьмём массив с числами «5 1 4 2 8» и отсортируем значения по возрастанию, используя сортировку пузырьком. Выделены те элементы, которые сравниваются на данном этапе.
Первый проход:
До | После | Описание шага |
---|---|---|
5 1 4 2 8 | 1 5 4 2 8 | Здесь алгоритм сравнивает два первых элемента и меняет их местами. |
1 5 4 2 8 | 1 4 5 2 8 | Меняет местами, так как 5 > 4 |
1 4 5 2 8 | 1 4 2 5 8 | Меняет местами, так как 5 > 2 |
1 4 2 5 8 | 1 4 2 5 8 | Теперь, ввиду того, что элементы стоят на своих местах (8 > 5), алгоритм не меняет их местами. |
Второй проход:
До | После | Описание шага |
---|---|---|
1 4 2 5 8 | 1 4 2 5 8 | |
1 4 2 5 8 | 1 2 4 5 8 | Меняет местами, так как 4 > 2 |
1 2 4 5 8 | 1 2 4 5 8 | |
1 2 4 5 8 | 1 2 4 5 8 |
Теперь массив полностью отсортирован, но неоптимизированный алгоритм проведет еще два прохода, на которых ничего не изменится, в отличии от оптимизированного, который сделает один проход и прекратит свою работу, так как не сделает за этот проход ни одного обмена.