Коли використовується кожен алгоритм сортування? [зачинено]


170

Які випадки використання, коли певний алгоритм сортування віддається перевагу порівняно з іншими - сортування злиття проти QuickSort проти Heapsort проти «введення сортування» тощо?

Чи є рекомендований посібник щодо їх використання залежно від розміру, типу структури даних, наявної пам'яті та кешу та продуктивності процесора?


Набір анімації для різних типів даних і алгоритмів можна знайти на сторінці <a href=" sorting-algorithms.com/"> sorting-algorithms.com </ а >
Chip Uni

2
Посібник, як bigocheatsheet.com для цього матеріалу, буде змащувати
K - Токсичність в SO зростає.

@ChipUni - це фіксоване посилання: toptal.com/developers/sorting-algorithms
eric

2
Чому це питання закрите !?
Арванд

Відповіді:


316

По-перше, визначення, оскільки це досить важливо: стабільний сорт - це те, що гарантовано не переставляє елементи однаковими ключами.

Рекомендації:

Швидкий сортування: коли вам не потрібен стабільний сортування, а середня ефективність випадку має значення, ніж найгірша ефективність. Швидкий сорт - в середньому O (N log N), у гіршому - O (N ^ 2). Хороша реалізація використовує O (log N) допоміжне сховище у вигляді простору стеку для рекурсії.

Сортування сортування: Коли вам потрібен стабільний, O (N log N) сортування, це лише ваш єдиний варіант. Єдиним недоліком цього є те, що він використовує допоміжний простір O (N) і має трохи більшу константу, ніж швидкий сортування. Існують деякі різновиди злиття на місці, але AFAIK всі вони або не стабільні, або гірші, ніж O (N log N). Навіть сорти O (N log N) мають настільки велику константу, ніж звичайний старий сорт злиття, що вони більше теоретичні цікавості, ніж корисні алгоритми.

Сортування купи: Коли вам не потрібен стабільний сорт, і вам більше важливо гірший показник, ніж середній показник. Це гарантовано O (N log N), і він використовує допоміжний простір O (1), це означає, що вам несподівано не вистачить місця з кучі чи стеку на дуже великих входах.

Introsort: Це швидкий сорт, який переходить до сортування купи після певної глибини рекурсії, щоб обійти найгірший випадок швидкого сортування (N ^ 2). Це майже завжди краще, ніж звичайний старий швидкий сорт, оскільки ви отримуєте середній випадок швидкого сортування, із гарантованою продуктивністю O (N log N). Напевно, єдина причина використовувати сортування купи замість цього - в сильно обмеженій пам'яті системах, де O (log N) простір стеків практично значний.

Сортування вставки : Коли N гарантовано буде невеликим, в тому числі в якості базового випадку швидкого сортування або сортування. Хоча це O (N ^ 2), він має дуже малу константу і є стабільним сортом.

Сортування бульбашок, сортування вибору : коли ви робите щось швидке і брудне, і ви чомусь не можете просто використовувати стандартний алгоритм сортування бібліотеки. Єдиною перевагою, яку вони мають перед сортуванням вставок, є те, що вона трохи легша у виконанні.


Сортування порівняння: За деяких досить обмежених умов можна зламати бар'єр O (N log N) і сортувати в O (N). Ось кілька випадків, коли варто спробувати:

Сортування підрахунку: Коли ви сортуєте цілі числа з обмеженим діапазоном.

Сортування радікса: Коли log (N) значно більший за K, де K - кількість цифр радіасу.

Сортування відра: Коли ви можете гарантувати, що ваш внесок приблизно рівномірно розподілений.


1
Як я пам’ятаю, сортування купи також має дуже передбачуваний час роботи, оскільки між різними входами однакового розміру є невеликі розбіжності, але це менш цікаво, ніж його постійний простір. Я також вважаю, що сортування вставок найпростіше здійснити з n ^ 2 сортів, але, можливо, це лише я. Нарешті, ви також можете згадати сорт Shell, який практично такий же простий у виконанні, як сортування вставки, але має кращі показники, хоча все ще не n n n n
JaakkoK

29
Не забувайте Богосорт ! ;-)
Алекс Брасевік

2
+1 Дуже цікаво. Чи хотіли б ви пояснити, як ви можете "гарантувати ... приблизно рівномірно розподілені". для сортування відра?
Сем Овертон

2
Чому б інтросорт був значно повільнішим, ніж швидкий сортування? Єдина накладні витрати - це підрахунок глибини рекурсії, яка повинна бути незначною. Він перемикається лише після рекурсії набагато глибше, ніж це має бути в хорошому випадку швидкого сортування.
dimimcha

2
Ви не зазначаєте, що найкращим випадком сортування бульбашок є O (n)!
Тара

33

Як правило, Quicksort є найшвидшим в середньому, але він має дуже неприємні поведінки в гіршому випадку. Тож якщо вам доведеться гарантувати, що погані дані не дають вам O(N^2), вам слід уникати цього.

Злиття-сортування використовує додаткову пам’ять, але особливо підходить для зовнішнього сортування (тобто величезні файли, які не вміщуються в пам'ять).

Heap сортування можна сортувати на місці і не має найгірший випадок квадратне поведінки, але в середньому повільніше , ніж швидке сортування в більшості випадків.

Там, де задіяні лише цілі числа в обмеженому діапазоні, ви можете використовувати якийсь сорт радіації, щоб зробити його дуже швидким.

У 99% випадків вам буде добре з бібліотечними видами, які, як правило, базуються на швидкості.


6
+1: бо "У 99% випадків ви будете добре з бібліотечними видами, які зазвичай базуються на швидкості".
Джим Г.

Рандомізоване перетворення дає Quicksort час виконання O (nlogn) для всіх практичних цілей, не потребуючи жодних гарантій щодо поганих даних. Я дійсно не думаю, що ніхто не реалізує O (n ^ 2) швидкості для будь-якого виробничого коду.
МАК

2
MAK, за винятком, скажімо, стандартної бібліотеки С qsort? ( google.com/codesearch/… ) - на який покладається більшість типів "виробничого коду"
Елі Бендерський,

Сортування бібліотеки зазвичай не базується на швидкості, оскільки вона не є стабільною. Майже всі вищі мови (очікуємо на С) забезпечують стабільне сортування. У більшості випадків я знаю, що вам потрібен стабільний або хоча б детермінований сорт.
12431234123412341234123


3

Надані посилання на порівняння / анімації не враховують, коли кількість даних перевищує доступну пам'ять ---, в цей момент кількість переходів над даними, тобто витрати вводу / виводу, домінують під час виконання. Якщо вам потрібно це зробити, читайте про "зовнішнє сортування", яке зазвичай охоплює варіанти сортування злиття та купи.

http://corte.si/posts/code/visualisingsorting/index.html та http://corte.si/posts/code/timsort/index.html також мають кілька цікавих зображень, що порівнюють різні алгоритми сортування.


0

@dsimcha пише: Підрахунок сортування: Коли ви сортуєте цілі числа з обмеженим діапазоном

Я змінив би це на:

Сортування підрахунку: Коли ви сортуєте додатні цілі числа (0 - Integer.MAX_VALUE-2 за рахунок голубого отвору).

Завжди можна отримати значення max і min як евристику ефективності в лінійний час.
Також вам потрібно принаймні n додаткового місця для проміжного масиву, і він очевидно стабільний.

/**
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

(навіть якщо це фактично дозволить MAX_VALUE-2) див .: Чи мають масиви Java максимальний розмір?

Також я б пояснив, що складність радіоскопічного сортування становить O (wn) для n клавіш, які є цілими числами розміру слова w. Іноді w подається як константа, яка б зробила сортування radix кращим (для достатньо великого n), ніж найкращі алгоритми сортування на основі порівняння, які виконують порівняння O (n log n) для сортування n клавіш. Однак загалом w не можна вважати постійною: якщо всі n клавіш чіткі, то w має бути принаймні log n, щоб машина з випадковим доступом могла зберігати їх у пам'яті, що дає в кращому випадку складність часу O (n журналу n). (з Вікіпедії)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.