Чому на практиці кращий кіксорт, ніж інші алгоритми сортування?


31

Це репост запитання на cs.SE від Janoma . Повні кредити та здобичі йому чи cs.SE.

У звичайному курсі алгоритмів нас вчать, що середній показник швидкості - це O (n log n) і O (n²) у гіршому випадку. У той же час вивчаються й інші алгоритми сортування, які є O (n log n) у гіршому випадку (наприклад, злиття та велика частина ), і навіть лінійний час у кращому випадку (як бульбашка ), але з деякими додатковими потребами пам'яті.

Після швидкого огляду на ще певні часи , природно сказати, що хитрощі не повинні бути настільки ефективними, як інші.

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

Чому ж тоді химерна перевага перевершує інші алгоритми сортування на практиці? Чи це стосується структури даних реального світу ? Це має відношення до способу роботи пам'яті в комп’ютерах? Я знаю, що деякі спогади проходять швидше, ніж інші, але я не знаю, чи це справжня причина цього контрінтуїтивного виконання (порівняно з теоретичними оцінками).


3
Репутація Quicksort датується часом, коли кеш не існував.
AProgrammer

9
"чому на практиці quicksort перевершує інші алгоритми сортування?" Впевнені, що це правда? Покажіть нам реальну реалізацію, на яку ви звертаєтесь із цим твердженням, і спільнота підкаже вам, чому саме така реалізація поводиться так, як це робить. Все інше призведе до диких здогадок про неіснуючі програми.
Док Браун

1
@DocBrown: Багато реалізацій Quicksort (або його варіантів) вибираються у багатьох бібліотеках, можливо, тому що вони працюють найкраще (я би сподівався, що так). Тож може бути щось про алгоритм, який робить Quicksort швидким, незалежно від реалізації .
Рафаель

1
Хтось повинен сказати це для повноти, тож я зроблю: Quicksort не (зазвичай) стійкий. З цієї причини ви можете не хотіти ним користуватися. Крім того, з цієї причини сорт за замовчуванням може бути не Quicksort, навіть коли це саме ви хочете.
РальфЧапін

1
@Raphael: Часто те, що називається швидким сортуванням, насправді є деяким варіантом, як введення сорту (використовується, afaik, у стандартній бібліотеці C ++), а не чисто швидке сортування.
Джорджо

Відповіді:


21

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

Для більшості цілей, Timsort - гібрид між об'єднанням / вставкою сортування, який використовує той факт, що дані, які ви сортуєте, часто починаються майже відсортованими або зворотно відсортованими.

Найпростіший швидкодіючий (не випадковий зсув) трактує цей потенційно поширений випадок як O (N ^ 2) (зведення до O (N lg N) випадковими поворотами), тоді як TimSort може обробляти ці випадки в O (N).

Відповідно до цих орієнтирів у C #, порівнюючи вбудований квакісорт з TimSort, Timsort значно швидше у більшості випадків сортування, а у випадку випадкових даних трохи швидше, а TimSort стає кращим, якщо функція порівняння є особливо повільною. Я не повторював ці орієнтири і не був би здивований, якби швидкий побіг злегка переміг TimSort за деякою комбінацією випадкових даних або якщо є щось вигадливе у вбудованому сорті C # (на основі quicksort), що уповільнює його. Однак TimSort має чіткі переваги, коли дані можуть бути частково відсортовані, і приблизно за рівнем швидкості дорівнює швидкості, коли дані не частково відсортовані.

TimSort також має додатковий бонус за стабільний сорт, на відміну від quicksort. Єдиним недоліком TimSort є використання O (N) проти O (lg N) пам'яті у звичайній (швидкій) реалізації.


18

Швидке сортування вважається більш швидким, оскільки коефіцієнт менший, ніж будь-який інший відомий алгоритм. Для цього немає ніяких причин і доказів, просто не знайдено алгоритм з меншим коефіцієнтом. Це правда, що інші алгоритми також мають O ( n log n ) час, але в реальному світі також важливий коефіцієнт.

Зауважте, що для малих введення даних сортування (те, що вважається O ( n 2 )) швидше через природу математичних функцій. Це залежить від конкретних коефіцієнтів, які різняться від машини до машини. (Зрештою, насправді працює лише збірка.) Тому іноді гібрид швидкого сортування та сортування вставляє найшвидший на практиці, я думаю.


7
+ Правильно. Вчителі повинні бути більш обізнаними (і я був учителем) того факту, що постійні фактори можуть змінюватися залежно від порядків. Тож навичка настройки продуктивності дійсно має значення, незалежно від big-O. Проблема полягає в тому, що вони продовжують викладати gprof , лише тому, що їм потрібно пройти ту точку пункту в навчальній програмі, що на 180 градусів - неправильний підхід.
Майк Данлі

2
"Для цього немає жодної причини або про [о] f: впевнений, що є. Якщо ви копаєте досить глибоко, ви знайдете причину.
Жил "ТАК - перестань бути злим"

2
@B Seven: щоб спростити багато… для алгоритму сортування O (n log n), існують (n log n) ітерації циклу сортування для сортування n елементів. Коефіцієнт - це тривалість циклу циклу. Коли n дійсно великий (принаймні тисячі), коефіцієнт має значення не стільки, скільки O (), навіть якщо коефіцієнт величезний. Але коли n малий, коефіцієнт має значення - і це може бути найголовніше, якщо ви сортуєте лише 10 елементів.
Метт Галлахер

4
@MikeDunlavey - хороший приклад - створення пірамід O (n), а сортування їх фотографій - O (n ln n), але це швидше!
Мартін Беккет

2
Існують гарантовані алгоритми O (n log n), такі як гипсорт і злиття, тому в асимптотичних умовах з найгіршим випадком Quicksort не є настільки ж швидким, як найкращий. Але в реальному світі деякі варіанти кваксортів надзвичайно добре. Однак сказати "коефіцієнт менший" - це як сказати "швидше, тому що швидше". Чому постійні фактори такі малі? Ключова причина - це те, що в місцевому відношенні дуже хороший кікспорт - він дуже добре використовує кеші. У Mergesort теж є хороший населений пункт, але зробити це на місці дуже важко.
Steve314

16

Quicksort не перевершує всі інші алгоритми сортування. Наприклад, сорт купи "знизу вгору" ( Wegener 2002 ) перевершує швидкий вибір за розумну кількість даних, а також є алгоритмом на місці. Це також легко здійснити (принаймні, не складніше, ніж якийсь оптимізований варіант швидкості).

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


+1: Я провів кілька тестів і дійсно сортування злиття було, безумовно, краще, ніж швидке сортування для великих масивів (> 100000 елементів). Сортування купи було трохи гірше, ніж сортування злиття (але для сортування об’єднання потрібно більше пам’яті). Я думаю, що те, що люди називають швидким сортуванням, часто є варіацією під назвою intro sort: швидкий сорт, який повертається до сортування купи, коли глибина рекурсії виходить за певну межу.
Джорджо

@Giorgio: quicksort можна змінити деякими способами, щоб покращити його, див. Наприклад тут: algs4.cs.princeton.edu/23quicksort Ви спробували ці покращення?
Док Браун

Цікаво, чи можете ви розмістити посилання на книгу \ сайт, щоб прочитати більше про неї? (бажано книгу)
Рамзі Кахіль

@Martin: ти маєш на увазі про недорогу грудку? Ну, я дав посилання вище. Якщо ви хочете отримати безкоштовний ресурс, у німецькій Вікіпедії є стаття про нього ( de.wikipedia.org/wiki/BottomUp-Heapsort ). Навіть якщо ви не розмовляєте німецькою мовою, я думаю, ви все ще можете прочитати приклад C99.
Док Браун

7

Ви не повинні зосереджуватися лише на гіршому випадку та лише на складності часу. Це більше про середнє, ніж гірше, і про час та простір.

Квікорт:

  • має середню часову складність Θ ( n log n );
  • може бути реалізований з просторовою складністю Θ (log n );

Також враховуйте, що велика нотація O не враховує жодних констант, але на практиці це має значення, якщо алгоритм у кілька разів швидший. Θ ( n log n ) означає, що алгоритм виконується в K  n  log ( n ), де K є постійним. Quicksort є алгоритм порівняння сортування з найменшим K .


1
@Gilles: у нього низький К, оскільки це простий алгоритм.
vartec

5
WTF? Це не має сенсу. Простота алгоритму не має відношення до його швидкості роботи. Сортування вибору простіше, ніж швидкодію, що не робить його швидшим.
Жил "ТАК - перестань бути злим"

1
@Gilles: сортування вибору O (n ^ 2) для будь-якого випадку (найгірший, середній і найкращий). Тож не має значення, наскільки це просто. Quicksort - це O (n log n) для середнього випадку, і серед усіх альгів з O (n log n) avg це найпростіший.
vartec

1
@ Gilles: за інших рівних умов простота сприяє продуктивності. Скажімо, ви порівнюєте два алгоритми, які приймають (K n log n) ітерації відповідних внутрішніх циклів: алгоритм, який повинен робити менше матеріалів на цикл, має перевагу в продуктивності.
буря,

1
@comingstorm: Висловлюється так, що ваше твердження є тавтологією, але воно не стосується "простоти". Наприклад, є більш складні варіанти Quicksort (відмінність випадків!), Які призводять до меншої тривалості виконання (як теоретично, так і на практиці).
Рафаель

5

Quicksort часто є хорошим вибором, оскільки він досить швидкий і досить швидкий і простий у виконанні.

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


1

Фактична ефективність алгоритмів залежить від платформи, а також мови, компілятора, уваги програміста до деталей реалізації, конкретних зусиль з оптимізації тощо. Таким чином, "перевага факторної переваги" квакірту не дуже чітко визначений - це суб'єктивне судження, засноване на наявних на даний момент інструментах, і приблизна оцінка "еквівалентних зусиль щодо впровадження" тим, хто насправді робить порівняльне дослідження ефективності. .

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

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


Я здогадуюсь, що "менша константа" інші пов'язують це з формальним аналізом, тобто за кількістю порівнянь або свопів. Це дуже чітко визначено, але незрозуміло, як це перекладається на час виконання. Зараз колега проводить деякі дослідження з цього приводу.
Рафаель

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

1
З тієї причини, яку ви констатуєте, говорити про загальну ефективність (за часом) не є сенсом в загальному випадку, оскільки фактор занадто багато деталей. Причина для підрахунку лише вибраних операцій полягає не в тому, що вони дорогі, а в тому, що вони відбуваються "найчастіше "у сенсі позначення Ландау (Big-Oh), тому підрахунок цих даних дає вам ваші грубі асимптотики. Як тільки ви розглядаєте константи та / або час виконання, ця стратегія стає набагато менш цікавою.
Рафаель

Хороша реалізація QuickSort складе так, що ваші зведені значення залишатимуться в регістрі процесора стільки часу, скільки вони потрібні. Цього достатньо часто, щоб перемогти теоретично швидший сорт із порівнянними часом Big-O.
Ден Ліонс

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