Почему быстрее n log n нельзя
Доказательство нижней оценки через дерево решений — и что именно оно запрещает, а что нет.
4 мин
Про сортировку часто говорят: «быстрее чем нельзя». Утверждение верное, но неполное — и без второй половины оно противоречит сортировке подсчётом, которая работает за линию.
Разберёмся, что именно доказано.
Что считается сортировкой сравнениями
Договоримся об алгоритме, который узнаёт о данных только через вопросы вида «верно ли, что ». Он может как угодно переставлять элементы, но заглянуть внутрь значения — узнать, что там 42, а не 43, — не может.
Под это определение попадают все сортировки из предыдущих статей: пузырёк, вставки, выбор, слияние, быстрая, пирамидальная. Не попадает подсчёт: он не сравнивает элементы между собой, а использует само значение как адрес в массиве счётчиков.
Дерево решений
Проследим за работой такого алгоритма на массиве из различных элементов. Первый его шаг — какое-то сравнение. В зависимости от ответа он делает второе сравнение, и так далее, пока не выдаст ответ.
Это дерево: узлы — сравнения, две ветви — «да» и «нет», листья — итоговые перестановки.
graph TD A["a₁ < a₂ ?"] -->|да| B["a₂ < a₃ ?"] A -->|нет| C["a₁ < a₃ ?"] B -->|да| D["1 2 3"] B -->|нет| E["a₁ < a₃ ?"] E -->|да| F["1 3 2"] E -->|нет| G["3 1 2"] C -->|да| H["2 1 3"] C -->|нет| I["..."]
Два наблюдения.
Листьев не меньше . Входных массивов, различающихся порядком, ровно штук, и каждому нужен свой ответ — своя перестановка. Если бы два разных входа приводили в один лист, алгоритм выдал бы для них одинаковый ответ, и для одного из них ответ был бы неверным.
Число сравнений в худшем случае — это глубина дерева. А двоичное дерево глубины имеет не больше листьев.
Складываем: , то есть
Сколько это
Оценим грубо, без формул. В произведении последняя половина сомножителей — каждый не меньше . Значит , откуда
Это уже . Точная оценка даётся формулой Стирлинга: .
Подставим настоящие числа. При получается около сравнений — любая сортировка сравнениями сделает не меньше. Это, кстати, и объясняет, почему -сортировки на таких размерах отрабатывают мгновенно: полтора миллиона сравнений процессору не страшны.
Что доказано, а что нет
Доказано: сортировка сравнениями делает сравнений в худшем случае. Заметьте — в худшем. Про конкретный вход это ничего не говорит: на уже отсортированном массиве вставки справляются за сравнений, и никакого противоречия нет.
Не доказано ничего про алгоритмы, которые сравнениями не ограничиваются. Отсюда все обходные пути:
- сортировка подсчётом использует значение как адрес и работает за ;
- поразрядная сортировка смотрит на разряды числа и работает за ;
- если данные уже почти отсортированы, оценка «в худшем случае» просто не про них.
Мораль практическая: если вам нужен именно полный порядок, данные произвольны и вы умеете только сравнивать — это потолок, и время лучше потратить на что-то другое. Если хоть одно из трёх условий нарушено, есть куда копать.
Полезное следствие
Из той же оценки следует, что поиск -й статистики — задача проще сортировки. Мы разобрали алгоритм за ; если бы можно было отсортировать за линию, отдельный алгоритм был бы не нужен. Нижняя оценка объясняет, почему он нужен: сортировка отвечает на более трудный вопрос и за это платит логарифмом.