Пузырьковая сортировка , иногда называемая сортировкой с понижением , представляет собой простой алгоритм сортировки , который многократно проходит по элементу входного списка, сравнивая текущий элемент с предыдущим, меняя их значения при необходимости. Эти проходы по списку повторяются до тех пор, пока во время прохода не нужно будет выполнять замены, что означает, что список стал полностью отсортированным. Алгоритм, представляющий собой сортировку сравнения , назван в честь того, как более крупные элементы «всплывают» вверх списка.
Этот простой алгоритм плохо работает в реальных условиях и используется в основном в качестве образовательного инструмента. Более эффективные алгоритмы, такие как быстрая сортировка , тимсортировка или сортировка слиянием, используются библиотеками сортировки, встроенными в популярные языки программирования, такие как Python и Java. Однако, если параллельная обработка разрешена, пузырьковая сортировка выполняется за время O(n), что делает ее значительно быстрее, чем параллельные реализации сортировки вставками или сортировки выбором, которые не распараллеливаются так эффективно. [2] [3]
Самое раннее описание алгоритма пузырьковой сортировки было в статье 1956 года математика и актуария Эдварда Гарри Френда, [4] Сортировка в электронных компьютерных системах , [5], опубликованной в третьем выпуске третьего тома Журнала Ассоциации компьютерных вычислений. Machinery (ACM), как «алгоритм сортирующего обмена». Френд описал основы алгоритма, и, хотя первоначально его статья осталась незамеченной, несколько лет спустя она была заново открыта многими учеными-компьютерщиками, включая Кеннета Э. Айверсона , который придумал его нынешнее название.
Пузырьковая сортировка имеет наихудшую и среднюю сложность , где — количество сортируемых элементов. Большинство практических алгоритмов сортировки имеют значительно лучшую сложность в наихудшем или среднем случае, часто . Даже другие алгоритмы сортировки, такие как сортировка вставками , обычно работают быстрее, чем пузырьковая сортировка, и не более сложны. По этой причине пузырьковая сортировка на практике используется редко.
Как и сортировка вставками , пузырьковая сортировка является адаптивной , что дает ей преимущество перед такими алгоритмами, как быстрая сортировка . Это означает, что он может превзойти эти алгоритмы в тех случаях, когда список уже в основном отсортирован (имеет небольшое количество инверсий ), несмотря на то, что он имеет худшую временную сложность в среднем случае. Например, пузырьковая сортировка выполняется в уже отсортированном списке, а быстрая сортировка все равно будет выполнять весь процесс сортировки.
Хотя любой алгоритм сортировки можно реализовать на основе предварительно отсортированного списка, просто проверив его перед запуском алгоритма, повышение производительности на почти отсортированных списках труднее воспроизвести.
Расстояние и направление, в котором элементы должны двигаться во время сортировки, определяют производительность пузырьковой сортировки, поскольку элементы движутся в разных направлениях с разной скоростью. Элемент, который должен переместиться в конец списка, может перемещаться быстро, поскольку он может участвовать в последовательных заменах. Например, самый большой элемент в списке выиграет каждую замену, поэтому он перемещается на отсортированную позицию при первом проходе, даже если он начинается ближе к началу. С другой стороны, элемент, который должен двигаться к началу списка, не может двигаться быстрее, чем на один шаг за проход, поэтому элементы движутся к началу очень медленно. Если самый маленький элемент находится в конце списка, потребуется несколько проходов, чтобы переместить его в начало. Это привело к тому, что эти типы элементов были названы кроликами и черепахами соответственно в честь персонажей басни Эзопа « Черепаха и Заяц» .
Были предприняты различные усилия по уничтожению черепах, чтобы повысить скорость сортировки пузырьков. Коктейльная сортировка — это двунаправленная пузырьковая сортировка, которая идет от начала до конца, а затем меняет направление, переходя от начала к началу. Он может довольно хорошо перемещать черепах, но сохраняет сложность наихудшего случая. Гребенчатая сортировка сравнивает элементы, разделенные большими промежутками, и может очень быстро перемещать черепах, прежде чем переходить к все меньшим и меньшим промежуткам, чтобы сгладить список. Его средняя скорость сравнима с более быстрыми алгоритмами, такими как быстрая сортировка .
Возьмите массив чисел «5 1 4 2 8» и отсортируйте его от наименьшего числа к наибольшему с помощью пузырьковой сортировки. На каждом этапе сравниваются элементы, выделенные жирным шрифтом . Потребуются три пропуска;
Теперь массив уже отсортирован, но алгоритм не знает, завершен ли он. Алгоритму требуется еще один полный проход без какой-либо замены, чтобы понять, что он отсортирован.
В псевдокоде алгоритм можно выразить как (массив с отсчетом от 0):
процедура bubbleSort ( A : список сортируемых элементов ) n := длина ( A ) повторение заменено := false for i := от 1 до n - 1 включительно do { если эта пара не в порядке } if A [ i - 1 ] > A [ i ] then { поменяйте их местами и запомните, что что-то изменилось } swap ( A [ i - 1 ] , A [ i ]) поменяно местами : = true end if end for до тех пор, пока не будет заменено завершение процедуры
Алгоритм пузырьковой сортировки можно оптимизировать, заметив, что n -й проход находит n -й по величине элемент и помещает его на последнее место. Таким образом, внутренний цикл может избежать просмотра последних n - 1 элементов при запуске в n -й раз:
процедура bubbleSort ( A : список сортируемых элементов ) n := длина ( A ) повторение заменено := false for i := от 1 до n - 1 включительно do if A [ i - 1 ] > A [ i ] затем поменяйте местами ( A [ i - 1 ] , A [ i ]) заменено := true end if end for n := n - 1 до тех пор, пока не будет заменена процедура завершения
В более общем плане может случиться так, что за один проход в конечное положение будет помещено более одного элемента. В частности, после каждого прохода все элементы после последней замены сортируются и их не нужно проверять повторно. Это позволяет нам пропускать многие элементы, что приводит к увеличению числа сравнений в наихудшем случае примерно на 50 % (хотя и без улучшения количества подкачек), и добавляет очень мало сложности, поскольку новый код включает в себя «подкачанную» переменную:
Чтобы реализовать это в псевдокоде, можно написать следующее:
процедура bubbleSort ( A : список сортируемых элементов ) n := длина ( A ) повторение newn := 0 for i := от 1 до n - 1 включительно do if A [ i - 1 ] > A [ i ] затем поменяйте местами ( A [ i - 1 ] , A [ i ]) newn := i end if end for n := newn до n ≤ 1 завершить процедуру
Альтернативные модификации, такие как сортировка шейкером, пытаются улучшить производительность сортировки пузырьком, сохраняя при этом ту же идею многократного сравнения и замены соседних элементов.
Хотя пузырьковая сортировка является одним из самых простых для понимания и реализации алгоритмов сортировки, ее сложность O ( n2 ) означает, что ее эффективность резко падает в списках , содержащих большое количество элементов. Даже среди простых алгоритмов сортировки O ( n 2 ) такие алгоритмы, как сортировка вставками , обычно значительно более эффективны.
Из-за своей простоты пузырьковая сортировка часто используется для ознакомления студентов , изучающих информатику, с концепцией алгоритма или алгоритма сортировки . Однако некоторые исследователи, такие как Оуэн Астрахан, приложили все усилия, чтобы принизить пузырьковую сортировку и ее продолжающуюся популярность в образовании в области информатики, рекомендуя ее вообще больше не преподавать. [6]
The Jargon File , в котором известно, что bogosort называется «архетипическим [sic] извращенно ужасным алгоритмом», также называется пузырьковая сортировка «обычным плохим алгоритмом». [7] Дональд Кнут в книге «Искусство компьютерного программирования» пришел к выводу, что «пузырьковая сортировка, похоже, не дает никаких рекомендаций, кроме запоминающегося названия и того факта, что она приводит к некоторым интересным теоретическим проблемам», некоторые из которых он затем обсуждает. . [8]
Пузырьковая сортировка асимптотически эквивалентна по времени выполнения сортировке вставками в худшем случае, но эти два алгоритма сильно различаются по количеству необходимых перестановок. Экспериментальные результаты, такие как результаты Астрахана, также показали, что сортировка вставками работает значительно лучше даже со случайными списками. По этим причинам многие современные учебники по алгоритмам избегают использования алгоритма пузырьковой сортировки в пользу сортировки вставками.
Пузырьковая сортировка также плохо взаимодействует с современным оборудованием ЦП. Он производит как минимум в два раза больше операций записи, чем сортировка вставкой, в два раза больше промахов в кэше и асимптотически больше ошибочных предсказаний ветвей . [ Требуется цитирование ] Эксперименты Астрахана по сортировке строк в Java показывают, что пузырьковая сортировка примерно на одну пятую быстрее сортировки вставкой и на 70% быстрее сортировки выбором . [6]
В компьютерной графике пузырьковая сортировка популярна благодаря своей способности обнаруживать очень небольшие ошибки (например, замену всего двух элементов) в почти отсортированных массивах и исправлять их с линейной сложностью (2 n ). Например, он используется в алгоритме заполнения полигонов, где ограничивающие линии сортируются по координате x в конкретной строке развертки (линии, параллельной оси x ) и с увеличением y их порядок меняется (два элемента меняются местами) только при пересечения двух прямых. Пузырьковая сортировка — это стабильный алгоритм сортировки, подобный сортировке вставками.
Пузырьковую сортировку иногда называют «тонущей сортировкой». [9]
Например, Дональд Кнут описывает вставку значений в желаемое место или по направлению к нему как возможность «[значению] установиться на надлежащий уровень» и что «этот метод сортировки иногда называют методом просеивания или погружения ». [10]
Эти дебаты увековечиваются из-за легкости, с которой можно рассматривать этот алгоритм с двух разных, но одинаково обоснованных точек зрения:
В интервью 2007 года бывший генеральный директор Google Эрик Шмидт спросил тогдашнего кандидата в президенты Барака Обаму о том, как лучше всего отсортировать миллион целых чисел ; Обама сделал паузу на мгновение и ответил: «Я думаю, что сортировка по пузырю была бы неправильным путем». [11] [12]
{{cite AV media}}
: CS1 maint: location (link)