Що таке найшвидший алгоритм сортування масиву цілих чисел?


55

Під час навчання в середній школі я натрапив на багато алгоритмів сортування. Однак я ніколи не знаю, який найшвидший (для випадкового масиву цілих чисел). Тому мої запитання:

  • Який найшвидший відомий в даний час алгоритм сортування?
  • Теоретично, чи можливі ще швидші? Отже, яка найменша складність для сортування?

7
Що ви маєте на увазі під швидким? Що ти хочеш виміряти?
Рафаель

2
Що означає "випадковий масив цілих чисел"? Випадково з яким розподілом? рівномірний розподіл? Гаусса? Залежно від розподілу, алгоритми очікуваного часу роботи можуть бути кращими за . O(nlogn)
Бакуріу

@gen Поглянь на сорт Radix. Наприклад, правильна реалізація має складність O (n) для Int32.
це

Погляньте на тест сортування
adrianN

1
@gen: З точки зору асимптотики? Тоді це легко: виберіть будь-який з Θ ( n log n ) алгоритмів. Зауважте, що це може не мати нічого спільного з (середнім) показником у реальному світі. Про це, можливо, варто прочитати з цього приводу. ΘΘ(nlogn)
Рафаель

Відповіді:


42

Загалом, існують алгоритми сортування , такі як сортування вставок, сортування міхурів та вибір виділення, які зазвичай слід використовувати лише в особливих обставинах; Quicksort, що є в гіршому випадку O ( n 2 ), але досить часто O ( n log n ) з хорошими константами та властивостями і який може бути використаний як процедура сортування загального призначення; Про ( п увійти п ) алгоритми, такі як злиття-сортування і купу сортування, які також є хорошими алгоритмами загального призначення сортування; і О ( нO(n2)O(n2)O(nlogn)О(нжурналн)О(н)або лінійні алгоритми сортування списків цілих чисел, таких як радіакс, відро та типи підрахунку, які можуть бути придатними залежно від природи цілих чисел у ваших списках.

Якщо елементи у вашому списку такі, що все, що ви знаєте про них, є загальним співвідношенням порядку між ними, то оптимальні алгоритми сортування матимуть складність Ω(нжурналн) . Це досить класний результат і той, для якого ви зможете легко знайти деталі в Інтернеті. Лінійні алгоритми сортування використовують додаткову інформацію про структуру елементів, що підлягають сортуванню, а не просто загальне відношення порядку між елементами.

Ще загальніше, оптимальність алгоритму сортування тісно залежить від припущень, які ви можете зробити про тип списків, які ви будете сортувати (а також машинну модель, за якою буде запускатись алгоритм, що може зробити навіть інакше поганим сортування алгоритми найкращий вибір; розглянути сортування бульбашок на машинах із стрічкою для зберігання). Чим сильніше ваші припущення, тим більше кутів може скоротити ваш алгоритм. За дуже слабких припущень про те, наскільки ефективно можна визначити "сортованість" списку, оптимальною складністю в гіршому випадку може бути навіть .Ω(н!)

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


Я думаю, деякі з цих повинні бути Ω ? ОΩ
Рафаель

1
@Рафаель Мех. Я думаю , що більшість з них , по всякому разі. Я вважаю, що нижня межа, мабуть, краще відображається Ω . Я поміняю пару з них, які мають найбільше сенсу. ΘΩ
Patrick87

7
Я голосую @Raphael отримує капелюх поліцейських : PΩ
Realz Slaw

2
@RealzSlaw: Я б з гордістю носив це. :]
Рафаель

1
@gen Див stackoverflow.com/a/3274203 для деякого обговорення. В основному, якщо окремих записів величезна кількість, і вони не зберігаються у випадковому доступі, а обсяг даних такий, що це потрібно робити на місці, то сортування бульбашок - це шлях. Ці обставини в наш час зазвичай рідкісні, але ви все ще можете зіткнутися з ними.
Patrick87

16

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

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

Але реально, на практиці алгоритм сортування рідко є головним вузьким місцем.


9

Крім того, відповідаючи на ваше друге запитання

Теоретично, чи можливі ще швидші?
Отже, яка найменша складність для сортування?

Для сортування загального призначення складність задачі на сортування на основі порівняння становить Ω (n log n) . Є деякі алгоритми, які виконують сортування в O (n), але всі вони покладаються на створення припущень про вхідні дані і не є алгоритмами сортування загального призначення.

В основному складність задається мінімальною кількістю порівнянь, необхідних для сортування масиву (log n являє собою максимальну висоту дерева бінарних рішень, побудованого при порівнянні кожного елемента масиву).

Офіційний доказ сортування складності нижньої межі ви можете знайти тут :


3
Ця відповідь не зовсім правильна. не є універсальною нижньою межею для сортування. Ця нижня межа застосовується лише до сортування на основі порівняння , тобто алгоритмів сортування, які використовують лише порівняння. Деякі алгоритми сортування не засновані на порівнянні. Заява "Є деякі алгоритми, які виконують сортування в O (n), але всі вони покладаються на створення припущень про вхідні дані і не є алгоритмами сортування загального призначення". може бути трохи оманливим - будьте обережні. Radix-sort - це алгоритм сортування загального призначення (якщо ви сортуєте цілі числа з фіксованою шириною). Ω(нжурналн)
DW

Залежить від того, що ви маєте на увазі під проблемою сортування . Сортування на основі загального призначення не є єдиним видом проблем із сортуванням у людей.
Patrick87

1
Це правда, звичайно. Я мав би бути більш конкретним, дякую, що вказав на це. Однак мені було трохи цікаво, про які інші підходи до сортування (а не на основі порівняння) ви мали на увазі; Radix Sort - це саме такий тип алгоритму O (n), про який я говорив - ви повинні «припустити» щось про вхідні дані (цілі числа з фіксованою шириною). У цьому сенсі це не алгоритм сортування загального призначення, правда?
rla4

1
@DW: сортування Radix не слід вважати алгоритмом сортування загального призначення, оскільки для нього потрібні цілі клавіші фіксованої довжини; чи не корисно інакше. Але я розумію вашу думку. :) Я думаю, що моя помилка була зосереджена на сортуванні всього, що можна порівняти, а не сортувати цілі числа . Вони різні проблеми і мають різний набір можливих рішень. У питанні згадується "випадковий масив цілих чисел", але я визнаю, що я взяв це як приклад, а не обмеження.
rla4

2
@DavidRicherby, озираючись на це через півтора року, я згоден з вами. Дякую.
DW

3

Найшвидший алгоритм сортування цілих чисел з точки зору найгіршого випадку, з яким я зіткнувся, - це Andersson et al. Він має найгірший випадок , що, звичайно, швидше, ніж O ( n log n ) .О(нжурналжурналн)О(нжурналн)


2
Це дуже цікаво, але вам потрібно надати більше інформації. Оскільки ви згадуєте , я припускаю, що вам відомо, що сортування на основі порівняння загальних цілих чисел, ймовірно, вимагає часу Ω ( n log n ) . Що-небудь асимптотично швидше, ніж це, повинно робити припущення щодо даних: наприклад, сортування radix працює в лінійному часі, припускаючи, що кожен елемент масиву максимум є деякою постійною. За яких умов цей алгоритм сортується в O ( n log log n ) і як він працює на практиці щодо інших алгоритмів, таких як сортування quicksort та radix? нжурналнΩ(нжурналн)О(нжурналжурналн)
Девід Річербі

1

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

Ан(н-1)А(н-1)Ω(н)О(н)Ω(н)

Ω(н)О(н)н2н3н-51н2


О(н)нlgнн232О(н)О(нlgн)(для кваксорту або злиття) на практиці порівняння не є настільки зрозумілим: константи, приховані в нотації big-O, стають дуже важливими, а константа для сортирування radix вище, ніж константа для quicksort або mergesort.
DW

лг(н)н

Ω(н)

2
О(шн)шшш{0,,2ш-1}журналннш=журналннжурналн.
Девід Річербі

1

О(нлоглогн)
О(нлоглогU)U


0

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

Теоретично, наприклад, quick_sortє O(n log n). З pпроцесорами в ідеалі це має зводитися, O(n/p log n)якщо ми будемо виконувати їх паралельно.

Цитувати Вікіпедію: Складність часу ...

Оптимальне паралельне сортування - O (log n)

На практиці таких масштабних розмірів введення неможливо було досягти O(log n)через масштабованість.

Ось псевдокод для паралельного злиття сортування . Реалізація merge()може бути такою ж, як і у звичайному вигляді злиття:

// Sort elements lo through hi (exclusive) of array A.
algorithm mergesort(A, lo, hi) is
    if lo+1 < hi then  // Two or more elements.
        mid = ⌊(lo + hi) / 2⌋
        fork mergesort(A, lo, mid)
        mergesort(A, mid, hi)
        join
        merge(A, lo, mid, hi)

Також дивіться:


О(н2)

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