ГоловнаСтаттіАлгоритми

Сортування Алгоритмами: Від бульбашкового до радяного сортування

Жоден алгоритм, заснований на порівнянні елементів, не зможе досягти кращої продуктивності, ніж n log n — але алгоритми, які повністю уникають порівняння елементів, можуть сортувати лінійним часом.

mysimulator teamОновлено — червень 2026≈ 9 хв читання▶ Відкрити симуляцію

Нижня межа сортування порівнянням

Сортування порівнянням приймає рішення про порядок елементів лише на основі порівняння пар елементів. Існує n! можливих порядків для n елементів, і бінарне дерево прийняття рішень, яке розрізняє всі ці порядки, потребує висоти щонайменше ⌈log₂(n!)⌉, що за апроксимацією Стирлінга дорівнює Θ(n log n). Це інформаційно-теоретичний нижній поріг: будь-який алгоритм сортування порівнянням потребує щонайменше Ω(n log n) порівнянь у найгіршому випадку. Сортування злиттям та сортування кучем досягають цього порогу в найгіршому випадку; швидке сортування досягає його лише в середньому, погіршуючись до O(n²) при ворожому вході даних. Стабільне сортування зберігає відносну послідовність елементів з однаковими значеннями — сортування за прізвищем повинно підтримувати Джона Сміта раніше, ніж Джейн Сміт.

Сортування алгоритмами: аналіз складності та стратегій

Insertion sort є O(n) на майже відсортованих даних і є правильним вибором для невеликих масивів або онлайн-даних, що надходять по одному елементу за раз. Merge sort розділяє масив навпіл, рекурсивно сортує кожну половину, а потім об'єднує: T(n) = 2T(n/2) + O(n), що дає гарантований O(n log n) у найкращому, середньому та найгіршому випадках, стабільний, але не є in-place — він потребує O(n) допомісного простору. Python's Timsort і Java's Arrays.sort використовують знизу вгору варіант, який об'єднує попередньо існуючі відсортовані пробіли, досягаючи O(n) на майже відсортованих даних. Quicksort розділяє масив навколо півобливу: O(n log n) середнього з хорошим півом, O(n²) найгіршого випадку на відсортованому масиві з поганим — пом'якшено за допомогою вибору піва median-of-three, випадкових півів або Introsort's перемикання до heapsort після проходження порогового значення глибини рекурсії (використовується в C++'s std::sort).

Algorithm    Best        Average     Worst       Space   Stable  In-place
Insertion    O(n)        O(n²)       O(n²)       O(1)    Yes     Yes
Merge        O(n log n)  O(n log n)  O(n log n)  O(n)    Yes     No
Quicksort    O(n log n)  O(n log n)  O(n²)       O(log n) No     Yes
Heap Sort    O(n log n)  O(n log n)  O(n log n)  O(1)    No      Yes
Counting     O(n+k)      O(n+k)      O(n+k)      O(k)    Yes     No
Radix (LSD)  O(dn)       O(dn)       O(dn)       O(n+k)  Yes     No

Сортування за допомогою куч: Вихід за межі лінійного часу

Алгоритм сортування за допомогою кучі (heap sort) будує бінарний макс-кущ у часі O(n) (за алгоритмом Флойда побудови куща, а не n окремих вставлень), потім послідовно витягує максимальний елемент у часі O(log n) на кожному кроці, що гарантує O(n log n) у найгіршому випадку з додатковим простором O(1) — але це нестабільний алгоритм, і його випадковий доступ значно уповільнює роботу порівняно зі швидким сортуванням (quicksort) через пропуски в кеші (cache misses). Алгоритми, які повністю уникають порівнянь, можуть уникнути обмеження n log n: сортування за допомогою підрахунку (counting sort) підраховує кількість входжень елементів по відомому діапазону [0, k] та обчислює префіксні суми, що займає O(n+k) часу; сортування на основі розряду (radix sort) застосовує стабільне сортування за допомогою підрахунку до кожного розряду від найменшого до найбільшого, що займає O(d·(n+k)) часу, де d – кількість розрядів; сортування по контурах (bucket sort) розподіляє рівномірно розподілені дійсні числа в n контейнерів, що займає O(n) очікуваний час.

Часті запитання

Чому жоден алгоритм сортування на основі порівняння не може досягти продуктивності O(n log n)?

Алгоритми сортування на основі порівнянь визначають порядок лише шляхом порівняння пар елементів. Існує n! можливих порядків для n елементів, і дерево бінарних рішень, яке їх розрізняє, потребує висоти принаймні ⌈log2(n!)⌉, що за апроксимацією Стерлінга дорівнює Θ(n log n). Це жорсткий інформаційно-теоретичний нижній поріг — жоден алгоритм сортування на основі порівнянь, хоч якого він би був розумним, не зможе його перевершити в найгіршому випадку.

Як сортування підрахунком та радіального сортування можуть обійти межу n log n?

Вони повністю оминають цей нижній поріг, оскільки ніколи не порівнюють два елементи безпосередньо. Сортування підрахунком підраховує кількість входжень кожного значення в заданому діапазоні [0,k] та обчислює префіксні суми, що працює за часом O(n+k). Радіальне сортування застосовує стабільне сортування підрахунком до кожної позиції цифри від найменш значущої до найбільшої, що також працює за часом O(d·(n+k)) — обидва обмежені структурованими ключами, такими як обмежені цілі числа, а не випадковими порівнюваними об'єктами.

Що означає для алгоритму сортування стабільність?

Стабільне сортування зберігає відносний порядок елементів, які порівнюються як рівні — наприклад, сортування за прізвищем має зберегти Джона Сміта перед Джейн Сміт, якщо вони вже були в такому порядку. Merge sort, insertion sort, bubble sort, counting sort та radix sort є стабільними; quicksort та heap sort не є стабільними, оскільки вони виконують переміщення на великі відстані, які можуть переставляти рівні елементи.

Спробуйте наживо

Усе, що вище, працює прямо у вашому браузері — відкрийте the simulation і змінюйте параметри під час роботи. Нічого не встановлюється, нічого не завантажується на сервер, уся модель живе в одній вкладці.

▶ Відкрити симуляцію the simulation

Що ви знайшли?

Додати кроки відтворення (опційно)