Сортировка 1: пузырьком, выбором и вставками
Сортировка выбором делает ровно 45 сравнений на любом списке из 10 значений, перемешан ли он вначале или уже упорядочен.
Расставляем по порядку
Сортировать значит переставлять значения списка так, чтобы они шли от меньшего к большему (или по имени, дате, цене, в любом порядке, который можно сравнивать). Это одна из самых частых работ компьютера: контакты в телефоне, результаты поиска по релевантности, столбец таблицы по дате. Сортировка облегчает и другие задачи. Как показал прошлый урок, в отсортированном списке можно искать двоичным поиском, а повторы в отсортированном списке стоят рядом.
В этом уроке три простых способа. Все три сравнивают по два значения за раз и переставляют значения внутри того же списка. Их коротко писать и легко понять, и все три резко замедляются на длинных списках. Если понять, почему они замедляются, легче разобраться в быстрых способах из следующего урока. Всё время мы считаем две вещи: сравнения (вопрос «это значение больше того?») и обмены (два значения меняются местами).
Сортировка пузырьком: меняем местами соседей не по порядку
Сортировка пузырьком идёт вдоль списка и сравнивает каждую пару соседей. Если левый больше, она меняет их местами. После одного полного прохода наибольшее значение шаг за шагом доезжает до правого края, как всплывающий пузырёк, и больше ему двигаться не нужно. Следующий проход может остановиться на одно место раньше. Частое улучшение: следить за проходом без единого обмена. Это значит, что всё уже по порядку, и сортировку можно закончить раньше.
Проследим на списке [5, 1, 4, 2, 8]. Первый проход сравнивает 5 и 1 (обмен), 5 и 4 (обмен), 5 и 2 (обмен), 5 и 8 (оставляем): список стал [1, 4, 2, 5, 8], и 8 на месте. Второй проход сравнивает 1 и 4, 4 и 2 (обмен), 4 и 5, получается [1, 2, 4, 5, 8]. Третий проход сравнивает 1 и 2, затем 2 и 4, обменов нет, и сортировка останавливается. Итого: 4 + 3 + 2 = 9 сравнений и 4 обмена.
function bubbleSort(a) {
for (let pass = 0; pass < a.length - 1; pass++) {
let swapped = false;
for (let j = 0; j < a.length - 1 - pass; j++) {
if (a[j] > a[j + 1]) {
[a[j], a[j + 1]] = [a[j + 1], a[j]]; // обмен
swapped = true;
}
}
if (!swapped) break; // уже отсортирован
}
return a;
}Сортировка выбором: найди наименьшее и поставь следующим
Сортировка выбором работает так, как многие люди раскладывают карты в руке. Просмотри весь список, найди наименьшее значение и обменяй его на первую позицию. Затем просмотри остаток, найди наименьшее из оставшихся и обменяй его на вторую позицию, и так далее. На [5, 1, 4, 2, 8] первый просмотр находит 1 и меняет его с 5; второй находит 2 и меняет его с 5; последние два просмотра находят 4 и 5 уже на месте. Это всего 2 обмена, но просмотры всё равно делают 4 + 3 + 2 + 1 = 10 сравнений.
Сортировка выбором никогда не останавливается раньше. Даже на уже отсортированном списке ей всё равно нужно проверить каждое оставшееся значение, чтобы убедиться, что найдено наименьшее. Для n значений сравнения всегда в сумме дают (n − 1) + (n − 2) + … + 1 = n(n − 1)/2. Для 10 значений это 45; для 100 значений 4950; для 1000 значений 499 500. Её сильная сторона в малом числе обменов: не больше n − 1, и это важно, когда перемещать значение дорого.
Сортировка вставками: вставь каждое новое значение на место
Сортировка вставками держит левую часть списка отсортированной и наращивает её по одному значению. Она берёт следующее значение и двигает его влево, меняя с соседом, пока сосед не окажется не больше. Тогда значение стоит на своём месте среди отсортированных. На почти упорядоченном списке каждое новое значение сдвигается лишь на шаг-два, поэтому там сортировка вставками очень быстрая. На [5, 1, 4, 2, 8] она делает 7 сравнений и 4 обмена.
Перетащи, чтобы повернуть. Колёсико или щипок для масштаба.
Считаем обмены: инверсии
Есть изящный способ предсказать, сколько обменов нужно сортировке пузырьком и вставками. Посчитай инверсии: пары значений, которые стоят в неправильном порядке относительно друг друга. В [5, 1, 4, 2, 8] инверсии (5, 1), (5, 4), (5, 2) и (4, 2), всего четыре. Каждый обмен двух соседей, стоящих не по порядку, исправляет ровно одну инверсию и не создаёт новых, поэтому оба способа делают ровно 4 обмена. В обратном списке из n значений инвертирована каждая пара, n(n − 1)/2 инверсий, и это худший случай.
| Способ | Пример | Отсортирован (5 значений) | Обратный (4 значения) |
|---|---|---|---|
| Сортировка пузырьком | 9 / 4 | 4 / 0 | 6 / 6 |
| Сортировка выбором | 10 / 2 | 10 / 0 | 6 / 2 |
| Сортировка вставками | 7 / 4 | 4 / 0 | 6 / 6 |
В каждой ячейке: сравнения / обмены. Пример списка: [5, 1, 4, 2, 8]. Сортировка пузырьком здесь в варианте, который останавливается после прохода без обмена.
У всех трёх способов одна и та же слабость. В худшем случае каждый сравнивает примерно каждую пару значений, около n²/2 сравнений. Удвой список, и работа вырастет в четыре раза. Список в десять раз длиннее означает в сто раз больше работы. Для нескольких десятков значений это почти не важно; для миллиона это безнадёжно, и следующий урок показывает, как сделать гораздо лучше.
| сравнение | Вопрос, больше ли одно значение другого |
| обмен | Два значения меняются местами |
| проход | Один путь вдоль списка |
| сортировка пузырьком | Меняет местами соседей не по порядку; за каждый проход наибольшее всплывает в конец |
| сортировка выбором | Находит наименьшее из оставшихся и ставит его на следующее место обменом |
| сортировка вставками | Сдвигает каждое новое значение влево в отсортированную часть |
| инверсия | Пара значений, стоящих в неправильном порядке относительно друг друга |
| n(n − 1)/2 | Число пар из n значений |
- Сколько сравнений делает сортировка выбором на любом списке из 10 значений?
- Сколько инверсий в [3, 1, 2]?
- Сколько обменов делает сортировка вставками на [4, 3, 2, 1]?
- Какое значение после первого прохода сортировки пузырьком точно стоит на своём месте?
- Наименьшее, в начале
- Наибольшее, в конце
- Среднее значение
- Пока никакое
- Какой способ делает меньше всего обменов на [5, 1, 4, 2, 8]?
- Сортировка пузырьком
- Сортировка выбором
- Сортировка вставками
- Список уже отсортирован. Какой способ всё равно делает n(n − 1)/2 сравнений?
- Сортировка пузырьком с ранней остановкой
- Сортировка выбором
- Сортировка вставками
- Сколько сравнений делает сортировка пузырьком (с ранней остановкой) на [5, 1, 4, 2, 8]?
- Список из 1000 значений становится списком из 2000. Как примерно меняется работа сортировки вставками в худшем случае?
- Оно удваивается
- Растёт примерно в четыре раза
- Растёт на 1000 шагов
- Остаётся прежней
- Какой способ лучше всего подходит для почти отсортированного списка?
- Сортировка вставками
- Сортировка выбором
- Любой, они все одинаковы
- Сколько пар можно составить из 100 значений (число сравнений в худшем случае, n(n − 1)/2)?
- Расставь в порядке, в котором список [3, 1, 2] проходит через сортировку вставками.
- Сортировка пузырьком меняет местами соседей; каждый проход несёт наибольшее значение в конец.
- Сортировка выбором всегда делает n(n − 1)/2 сравнений и не больше n − 1 обменов.
- Сортировка вставками быстра на почти отсортированных списках.
- Сортировки пузырьком и вставками делают по одному обмену на инверсию.
- Всем трём в худшем случае нужно около n² шагов.
Источники курса (11)
- MIT OpenCourseWare 6.006 Introduction to Algorithms, Spring 2020 (Demaine, Ku, Solomon)
- lecture notes 1 Introduction, 3 Sorting, 9 Breadth-First Search, 10 Depth-First Search (ocw.mit.edu/courses/6-006-introduction-to-algorithms-spring-2020/pages/lecture-notes) and Fall 2011 lecture 13 BFS notes (ocw.mit.edu/courses/6-006-introduction-to-algorithms-fall-2011)
- Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (MIT Press)
- with the CLRS-based Khan Academy algorithms unit by Thomas Cormen and Devin Balkcom of Dartmouth (khanacademy.org/computing/computer-science/algorithms: binary search, selection sort analysis, merge sort, quicksort overview and analysis)
- MacTutor History of Mathematics, Al-Khwarizmi (mathshistory.st-andrews.ac.uk/Biographies/Al-Khwarizmi: word algorithm from the Latin title Algoritmi de numero Indorum)
- D. E. Joyce, Euclid's Elements Book VII Propositions 1 and 2 (mathcs.clarku.edu/~djoyce/elements/bookVII)
- Wolfram MathWorld, Merge Sort (mathworld.wolfram.com/MergeSort.html: proposed by John von Neumann in 1945, after Knuth 1998 p. 159)
- Stanford CS "Tony Hoare: Quicksort" (cs.stanford.edu/people/eroberts/courses/soco/projects/2008-09/tony-hoare/quicksort.html: devised while a student at Moscow State University for Russian-English machine translation with a tape dictionary, programmed in Algol 60 and published 1961; the year 1959 from the Wikipedia Quicksort article and its cited sources)
- Bodleian Libraries, Ada Lovelace (blogs.bodleian.ox.ac.uk/adalovelace: 1843 paper, Note G Bernoulli numbers)
- Fourmilab text of Menabrea's Sketch with Lovelace's notes (fourmilab.ch/babbage/sketch.html)
- Seven Bridges of Konigsberg (Euler 1736) and Tower of Hanoi (Edouard Lucas, 1883) checked against the Wikipedia articles and their cited sources.
Проверено: 2026-10-17