Сортировка (sorting) переставляет элементы массива так, чтобы они шли по порядку. Набор элементов не меняется — меняется только их расположение.

Зачем нужно

На лекции названы применения: фильтры, маркетплейсы, бинарный поиск. Бинарный поиск вообще работает только на отсортированном массиве.

Как работает

Определение

Было — стало , и

Виды порядка:

возрастание
неубывание
убывание
невозрастание

Не из лекции: равные элементы

При повторах строгого возрастания не бывает, поэтому «по возрастанию» на практике значит по неубыванию.

Свойства

Сортировки сравнивают по трём свойствам:

  • время выполнения ;
  • дополнительная память — см. Время работы алгоритма;
  • устойчивость (стабильность, stability) — сохраняется ли порядок одинаковых элементов.
устойчивая:     [1̇, 2, 1̈] → [1̇, 1̈, 2]
неустойчивая:   [1̇, 2, 1̈] → [1̈, 1̇, 2]

Не из лекции: когда устойчивость важна

Числа неотличимы, и для них разницы нет. Она появляется, когда сортируют записи по ключу: товары, уже упорядоченные по цене, сортируют по рейтингу. Устойчивая сортировка сохранит порядок цены внутри одного рейтинга, неустойчивая — нет.

Алгоритмы курса

АлгоритмУстойчива
тривиальный (перемешать и проверить)
выборомнет
вставкамида
пузырькомда

Не из лекции: тривиальный алгоритм

Перемешать стоит , а не , как на доске, — на итог это не влияет. Оценка — среднее: в среднем нужно попыток, но гарантированного времени нет. Подробно — в конспекте L03.

Тонкости

  • Одинаковая оценка не значит одинаковое поведение: выбор делает сравнений на любом входе, вставки на уже отсортированном массиве — . См. Квадратичные сортировки.
  • Устойчивость обычно решается одним знаком: где строгое сравнение, а где нестрогое.

Частые ошибки

  • Путать «отсортировать» с «переупорядочить как угодно»: элементы обязаны остаться те же, без потерь и дублей.
  • Считать устойчивость свойством результата. Отсортированный массив чисел выглядит одинаково — устойчивость видна только на записях с ключами.

Углубление — АиСД L04

Быстрее квадрата

Сортировка слиянием: , , устойчива.

АлгоритмУстойчива
выбором, вставками, пузырькомвыбор — нет, остальные — да
слияниемда

При квадратичная сортировка — около секунд, сортировка за — около 0,2 секунды. За скорость платят памятью.

Нижняя оценка

Теорема (о сортировках сравнением). Никакая сортировка сравнением не работает быстрее . На лекции — без доказательства.

Не из лекции: доказательство через дерево решений

Сортировка сравнением узнаёт о данных только одно: результаты сравнений пар элементов. Все её дальнейшие действия определяются этими результатами.

Нарисуем её работу на массиве из N разных элементов как двоичное дерево. Узел — сравнение, две ветки — два исхода, лист — конец работы. Каждый вход проходит по дереву путь от корня к листу.

Разные порядки входа ведут в разные листья. Если два входа с разным порядком элементов дошли до одного листа, алгоритм получил одинаковые ответы на все сравнения и переставил элементы одинаково. Одна и та же перестановка не может отсортировать оба входа — один из них останется неотсортированным.

Порядков , значит, листьев не меньше . У двоичного дерева высоты не больше листьев: , .

Оценка . Из множителей хотя бы не меньше , поэтому и

Высота дерева — число сравнений на худшем входе. ∎

Теорема говорит о худшем случае и только о сортировках сравнением: алгоритмы, которые пользуются значениями элементов иначе, чем сравнивая их, под неё не попадают.

Следствие: Сортировка слиянием с её асимптотически лучше сделать нельзя.

Углубление — АиСД L05

АлгоритмУстойчива
слияниемда
быстрая в среднем, в худшем на стекнет
подсчётомустойчивая версия — да

На доске у быстрой сортировки , а у подсчёта . В таблице — уточнённые оценки, разбор в конспекте L05.

Разные сортировки → разные константы. Слиянием и быстрая — обе , но быстрая не копирует элементы в буфер и обычно быстрее.

Сортировки не сравнением

Теорема о нижней оценке повторена на L05 без доказательства. Сортировка подсчётом её не нарушает: она не сравнивает элементы, а использует значение как индекс массива счётчиков. Поэтому линейное время возможно — но только для небольших целых значений.

Устойчивость у подсчёта — не знак сравнения, как у Merge, а направление прохода: устойчивая версия раскладывает элементы с конца массива.