# теория · шаг 1 из 7
Нижняя граница сравнений: почему быстрее n·log n нельзя
Коротко
Любая сортировка, которая упорядочивает элементы, СРАВНИВАЯ их друг с другом, не может в
худшем случае обойтись меньше чем Ω(n·log n) сравнениями - это ДОКАЗАННАЯ нижняя
граница, а не «пока не придумали лучше». Доказательство - дерево решений: каждое
сравнение - развилка на два исхода, а различить надо n! возможных порядков входа.
Дерево с n! листьями имеет высоту хотя бы log₂(n!) = Θ(n·log n), а высота - это
число сравнений в худшем случае. Значит слияние, быстрая и пирамидальная уже
асимптотически оптимальны СРЕДИ СОРТИРОВОК СРАВНЕНИЯМИ.
Если ты умеешь доказать нижнюю границу Ω(n·log n) деревом решений (n! листьев → высота log(n!) = Θ(n·log n)) и понимаешь, что она относится только к сортировкам сравнениями, листай до «Теперь сам».
Как думаешь, можно ли отсортировать сравнениями быстрее n·log n
Мы видели три сортировки за n·log n - слиянием, быструю, пирамидальную. Естественный
вопрос: а вдруг есть ещё умнее, за n или n·log log n? Для сортировок, которые
работают ТОЛЬКО через сравнения элементов («какой из этих двух больше?»), ответ строгий и
удивительный: НЕЛЬЗЯ. Не «не придумали», а доказано, что нельзя. И доказательство не
требует перебирать все алгоритмы - оно смотрит на саму ЗАДАЧУ и считает, сколько
информации сравнения способны добыть.
На что это похоже
Игра «угадай число от 1 до 1000» вопросами «да/нет». Каждый вопрос делит оставшиеся
варианты надвое, поэтому за k вопросов различишь не больше 2^k вариантов. Чтобы
покрыть 1000 вариантов, нужно k ≥ log₂ 1000 ≈ 10 вопросов - меньше физически не хватит
информации. Сортировка сравнениями - та же игра: каждое сравнение - вопрос «да/нет», а
«вариантов» (возможных исходных порядков) целых n!. Значит вопросов-сравнений нужно
хотя бы log₂(n!).
Механизм: дерево решений
Представим ЛЮБОЙ алгоритм сортировки сравнениями как дерево решений. Внутренний узел
- это одно сравнение (a[i] < a[j]?), у него два ребёнка: ветка «да» и ветка «нет».
Спускаясь от корня, алгоритм задаёт сравнения и в зависимости от ответов идёт влево или
вправо. Лист - это конец работы, где алгоритм выдаёт КОНКРЕТНУЮ перестановку как ответ.
Ключевые два факта:
- Листьев не меньше
n!. Вход изnразличных элементов может быть вn!порядках, и каждому нужен СВОЙ ответ (своя перестановка, возвращающая порядок). Если бы двух разных входов приводили к одному листу, на одном из них ответ был бы неверен. Значит разных достижимых листьев хотя быn!. - Высота дерева = число сравнений в худшем случае. Самый длинный путь от корня до листа - это самая длинная цепочка сравнений, которую алгоритм может сделать.
Двоичное дерево высоты h имеет не больше 2^h листьев. Раз листьев ≥ n!, то
2^h ≥ n!, откуда h ≥ log₂(n!).
Правило
Любая сортировка СРАВНЕНИЯМИ в худшем случае делает не меньше Ω(n·log n) сравнений.
Доказательство: алгоритм - это дерево решений с ≥ n! листьями (по листу на каждый из
n! порядков), а двоичное дерево с таким числом листьев имеет высоту ≥ log₂(n!) =
Θ(n·log n); высота - это число сравнений в худшем случае. Поэтому слияние, быстрая и
пирамидальная - уже оптимальны по порядку роста среди сортировок сравнениями.
Разбор: почему log₂(n!) - это Θ(n·log n)
Нужно показать, что log₂(n!) растёт как n·log n. Сверху: n! ≤ n^n, значит
log(n!) ≤ n·log n. Снизу: в произведении n! = 1·2·...·n возьмём только вторую
половину множителей - от n/2 до n, их n/2 штук, и каждый ≥ n/2. Тогда
n! ≥ (n/2)^(n/2), откуда log(n!) ≥ (n/2)·log(n/2) = Θ(n·log n). Зажали с обеих сторон
- значит log₂(n!) = Θ(n·log n). (Строже это даёт формула Стирлинга, но и грубой оценки
хватает.) Смысл: n! - астрономически большое число (log от него линеен по n с
множителем log n), и чтобы «различить» столько вариантов вопросами да/нет, вопросов
нужно порядка n·log n.
Разбор: граница про сравнения, а не про сортировку вообще
Важнейшая оговорка: Ω(n·log n) доказана для алгоритмов, которые узнают о данных ТОЛЬКО
через сравнения «больше/меньше». Если разрешить ДРУГИЕ операции - например, использовать
сами значения как индексы (адресоваться по значению, а не сравнивать), - граница НЕ
действует, и сортировать можно за линейное время. Именно так работают сортировка подсчётом
и поразрядная (следующие уроки): они не задают ни одного вопроса «что больше», а раскидывают
элементы по ячейкам, соответствующим их значению. Дерево решений к ним неприменимо, потому
что их шаги - не двоичные развилки-сравнения. Так что n·log n - это стена для одного
класса алгоритмов, а не закон природы для задачи сортировки.
Что ломается без этого
Первая ошибка - искать сортировку сравнениями быстрее n·log n в общем случае: это
потерянное время, доказано, что её нет. Понимать это - значит не гнаться за невозможным, а
принять n·log n как оптимум и выбирать между слиянием, быстрой и пирамидальной по ДРУГИМ
критериям (память, устойчивость, худший случай). Вторая ошибка - обратная: решить, что
n·log n - предел для ЛЮБОЙ сортировки, и пройти мимо линейных сортировок подсчётом там,
где данные это позволяют. Граница жёсткая, но узкая: она только про сравнения.
Зачем это в работе
Нижняя граница - это редкий и ценный инструмент: она говорит, когда ОСТАНОВИТЬСЯ в
оптимизации. Если твоя задача сводится к сортировке сравнениями и ты уже на n·log n -
дальше по порядку роста улучшать нечего, доказано; силы надо тратить на константу (кеш,
меньше обменов), а не на поиск мифического n. И наоборот: граница подсказывает обходной
путь - «а нельзя ли не сравнивать?». Если ключи - целые в разумном диапазоне, ответ «да»,
и открывается линейная сортировка. Умение доказать нижнюю границу и знать её область
действия отличает инженера, который понимает пределы, от того, кто их не видит.
Теперь сам
Почему сортировке трёх различных элементов нужно в худшем случае не меньше 3 сравнений, а не 2? Свяжи ответ с деревом решений.
Ответ. Трёх элементов можно расставить 3! = 6 способами, значит дереву решений нужно
не меньше 6 листьев (свой ответ на каждый порядок). Двоичное дерево высоты 2 имеет не
больше 2² = 4 листьев - этого мало для шести. Высоты 3 хватает: 2³ = 8 ≥ 6. Значит
высота дерева (число сравнений в худшем случае) не меньше ⌈log₂ 6⌉ = 3. Двумя сравнениями
шесть порядков не различить - информации не хватит, как двумя вопросами «да/нет» не угадать
один из шести вариантов. Это ровно log₂(n!) для n = 3.
Главное
Любая сортировка СРАВНЕНИЯМИ делает в худшем случае Ω(n·log n) сравнений - доказанная
нижняя граница. Доказательство деревом решений: каждое сравнение - развилка да/нет,
различить надо n! порядков, значит листьев ≥ n!, а высота двоичного дерева с таким
числом листьев ≥ log₂(n!) = Θ(n·log n) (высота = число сравнений в худшем случае).
Поэтому слияние, быстрая и пирамидальная уже оптимальны по порядку роста. Но граница -
ТОЛЬКО про сравнения: кто не сравнивает, а считает или адресуется по значению (подсчётом,
поразрядная), сортирует за линию.
Комментарии
Пока нет комментариев. Будь первым!
Оставить комментарий