Який алгоритм сортування найкраще працює в основному відсортованих даних? [зачинено]


174

Який алгоритм сортування найкраще працює в основному відсортованих даних?


Здогадуючись про відсутність контексту - ви запитуєте про сортування в пам'яті без необхідності розсипати проміжні результати на диск?
Джонатан Леффлер

1
Відповідно до цих анімацій, сортування вставки найкраще працює на переважно відсортованих даних.
dopple

Відповіді:


259

На основі високонаукового методу перегляду анімованих gif-файлів я б сказав, що "Insertion" і "Bubble" - хороші кандидати.


19
це прекрасне посилання, до речі, kudos та +1
дев’ятисторічний

5
Сорт бульбашок жахливий. Це завжди O (n ^ 2). Принаймні, вийміть це з своєї відповіді, щоб це було правильно, будь ласка.
jjnguy

79
jjnguy, це просто неправильно. Я думаю, вам потрібно знову взяти клас алгоритмів. На майже відсортованих даних (це адаптивний випадок) це O (N). Однак потрібно 2 проходи через дані, а Вставка лише 1 для майже відсортованих даних, що робить Вкладення переможцем. Бульбашка все-таки хороша, хоча
mmcdole

3
Ефективність погіршується дуже погано, якщо ваші дані колись майже не відсортовані. Я б все одно не користувався ним особисто.
Blorgbeard вийшов

5
Це посилання було розірвано, коли я його спробував. Спробуйте замість цього: sorting-algorithms.com
Michael La Voie

107

Лише кілька предметів => ВСТАНОВЛЕННЯ СОРТ

Елементи в основному сортуються вже => ВСТУП СОРТ

Стурбовано найгіршими сценаріями => HEAP SORT

Цікавить хороший середній випадок => ШВИДКО

Предмети витягнуті з щільного Всесвіту => BUCKET SORT

Бажання написати якомога менше коду => ВСТАНОВИТИЙ СОРТ


1
Це саме та відповідь, яку я шукав, я читав книги, але, здається, не знаходжу чіткого пояснення щодо вибору алогіоритмів у конкретних випадках, ви можете, будь ласка, розробити це або перейти посилання, щоб я міг собаку в це трохи більше? Спасибі
Simran kaur

9
Ви повинні додати "Дані вже відсортовано за іншим критерієм => МЕРГИЙ СОРТ"
Jim Hunziker

30

таймсорт

Timsort - це "адаптивний, стабільний, природний злиття" з " надприродними показниками на багатьох видах частково впорядкованих масивів (менше, ніж lg (N!) Зіставлень, необхідних і не менше N-1)". Вбудований Pythonsort()використовує цей алгоритм деякий час, очевидно, з хорошими результатами. Він спеціально розроблений для виявлення та переваги частково відсортованих послідовностей на вході, які часто трапляються в реальних наборах даних. У реальному світі часто трапляється так, що порівняння набагато дорожчі, ніж обмін предметами в списку, оскільки, як правило, просто поміняють покажчики, що дуже часто робить тимчасовий вибір прекрасним вибором. Однак, якщо ви знаєте, що ваші порівняння завжди дуже дешеві (наприклад, написання іграшкової програми для сортування 32-бітових цілих чисел), існують інші алгоритми, які, ймовірно, можуть працювати краще. Найпростіший спосіб скористатись тимчасовим стилем - це, звичайно, використовувати Python, але оскільки Python є відкритим кодом, ви також можете отримати позичальний код. Крім того, вищеописаний опис містить більш ніж достатньо деталей, щоб написати власну реалізацію.


16
log (n!) є Ο (n * log (n)), тому він не є "надприродним".
jfs

Ось реалізація Java, що надходить у JDK7: cr.openjdk.java.net/~martin/webrevs/openjdk7/timsort/raw_files/…
Тім

журнал (n!) не швидкий. wolframalpha.com/input/?i=plot evidencelog (N !) , {N, 0,1000}]
Behrooz

9
@JF Себастьян: timsort набагато швидше lg(n!)порівнянь на майже відсортованому масиві, аж до O(n)! | @behrooz: Ні порівняння сортування може мати середній випадок краще O(n log n), і lg(n!)це O(n log n). Тож найгірший випадок Timsort - асимптотично не гірший, ніж у будь-якого іншого порівняння. Крім того, його найкращий випадок кращий або рівний будь-якому іншому порівнянню.
Артелій

3
Тимсорт все ще є O (nlogn) в гіршому випадку, але його хороші випадки дуже приємні. Ось порівняння з деякими графіками: stromberg.dnsalias.org/~strombrg/sort-compitation Зауважимо, що timsort у Cython був не настільки швидким, як вбудований Python у timsort у C.
user1277476

19

Сортування вставки з такою поведінкою:

  1. Для кожного елемента kв слотах 1..nспочатку перевірте, чи немає el[k] >= el[k-1]. Якщо так, перейдіть до наступного елемента. (Очевидно, пропустити перший елемент.)
  2. Якщо ні, використовуйте бінарний пошук в елементах, 1..k-1щоб визначити місце вставки, а потім продемонструйте елементи. (Ви можете зробити це лише у тому випадку, k>Tколи де Tє порогове значення; при малому kце надмірність.)

Цей метод дає найменшу кількість порівнянь.


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

Через крок 1 для будь-яких елементів, які вже відсортовані, існує рівно одне порівняння та нульове переміщення даних, що, очевидно, найкраще, що ви можете зробити. Крок 2 - це той самий варіант, на якому ви могли б вдосконалитись, але міхур перемістить однакову кількість елементів і може мати більше порівнянь, залежно від вашої імпл.
Джейсон Коен

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

Я намагався реалізувати це, але двійковий пошук не дуже покращився, оскільки вам все одно доведеться перемістити весь блок, щоб вставити елемент. Тож замість 2xrange ви отримуєте range + logb (range).
це

11

Спробуйте інтроспективне сортування. http://en.wikipedia.org/wiki/Introsort

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

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

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

Якщо ви програміст на C ++, перевірте алгоритм std :: sort. Він може вже використовувати внутрішньоперспективний сортування внутрішньо.


7

Splaysort - незрозумілий метод сортування, заснований на хитрі дерева , тип адаптивного бінарного дерева. Splaysort хороший не лише для частково відсортованих даних, але й для частково зворотно-відсортованих даних, або взагалі будь-яких даних, що мають будь-який тип попереднього порядку. Це O (nlogn) у загальному випадку та O (n) у випадку, коли дані певним чином сортуються (вперед, назад, орган-труба тощо).

Його велика перевага перед сортуванням вставки полягає в тому, що він не повертається до поведінки O (n ^ 2), коли дані взагалі не сортуються, тому вам не потрібно бути абсолютно впевненим, що дані частково сортуються перед їх використанням .

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

Документ про splaysort був опублікований в Software - Practice & Experience.



5

Гладкий сорт Dijkstra - це чудовий сорт для вже відсортованих даних. Це важкий варіант, який працює в O (n lg n) в гіршому випадку і в O (n) кращому випадку. Я написав аналіз алгоритму, на випадок, якщо вам цікаво, як він працює.

Природний злиття - це ще один дійсно хороший для цього варіант - це варіант злиття знизу вгору, який працює, трактуючи вхід як об'єднання декількох різних відсортованих діапазонів, а потім використовуючи алгоритм злиття, щоб об'єднати їх разом. Ви повторюєте цей процес, поки не буде відсортовано весь діапазон введення. Це запускається в O (n) час, якщо дані вже відсортовані, а O (n lg n) в гіршому випадку. Це дуже елегантно, хоча на практиці це не так добре, як деякі інші адаптивні сорти, такі як Timsort або smoothsort.


які константи часу згладжування плавних скорочень порівняно з іншими алгоритмами сортування? (Тобто у час виконання (Плавне сортування) / виконання (сортування вставками) для тих же даних)
Arne Babenhauserheide

4

Якщо елементи вже відсортовані або є лише декілька елементів, це було б ідеальним випадком використання для сортування вставки!


3

Сортування вставки потребує часу O (n + кількість інверсій).

Інверсія - пара (i, j)такаi < j && a[i] > a[j] . Тобто, пара поза замовленням.

Одним із показників "майже відсортованого" є кількість інверсій --- можна вважати "майже відсортованими даними", щоб означати дані з малою кількістю інверсій. Якщо вам відомо, що кількість перетворень буде лінійною (наприклад, ви щойно додали елементи O (1) до відсортованого списку), сортування вставки потребує часу O (n).


2

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

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


2

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

Нехай N - кількість елементів, загальна, M - кількість поза замовленням.

Сорт бульбашки повинен буде зробити щось на зразок 2 * M + 1, що проходить через усі N елементів. Якщо M дуже маленький (0, 1, 2?), Я думаю, що це буде дуже важко перемогти.

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

Якщо M більший (скажімо, рівний або великий, ніж log N), інтроспективний сортування майже напевно найкращий.

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

Подальші думки (протягом ночі): Якщо M + 1 <N / M, ви можете сканувати список, шукаючи пробіг N / M у рядку, відсортованому, а потім розгорнути його в будь-якому напрямку, щоб знайти вихід -порядкові предмети. Це займе щонайбільше 2N порівнянь. Потім ви можете сортувати несортовані елементи та робити відсортоване об’єднання за двома списками. Загальне порівняння повинно бути меншим, ніж щось на зразок 4N + M log2 (M), який, на мою думку, переможе будь-яку неспеціалізовану процедуру сортування. (Ще думка далі: це складніше, ніж я думав, але я все ще думаю, що це розумно можливо.)

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


1

Якщо вам потрібна спеціальна реалізація для сортування алгоритмів, структур даних або будь-чого, що має посилання на вищезазначене, я можу порекомендувати вам чудові "Структури даних та алгоритми" на CodePlex?

У ньому буде все необхідне, не вигадуючи колесо.

Просто моє маленьке зерно солі.


1

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


0

Сортування вставки є найкращим випадком O (n) на відсортованому вході. І це дуже близько за впорядкованим введенням (краще, ніж швидке сортування).


0

розмірковуйте Спробуйте купи. Я вважаю, що це найбільш послідовний з видів O (n lg n).


Консистенція тут не хвилює. Heapsort дасть O (n lg n) навіть за відсортованими даними, і насправді не є адаптивним. Можливими варіантами можуть бути: сортування вставки, Тімсорт та Бабблсорт.
Макс

0

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


0

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


1
Цей "наскільки я переймаюся" тест ефективності алгоритму полегшив мені день :) Але якщо ви писали "видалити і вставити", ви мали на увазі Сортування вставки (про що вже говорилося в попередніх відповідях), чи ви пропонуєте новий вид алгоритму? Якщо так, будь ласка, розгорніть свою відповідь.
yoniLavi

0

Сорт бульбашки, безумовно, переможець Наступним на радарі буде сортування вставок.


4
опублікуйте свою відповідь із поясненням;

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

-1

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


-1 Кожна промислова реалізація Quicksort має обґрунтовану вибірку
Стефан Еггермонт

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