Найгірший випадок на місці стабільного сортування?


35

У мене виникають проблеми з пошуку хороших ресурсів, які дають найгірший випадок на місці стабільного алгоритму сортування. Хтось знає про якісь хороші ресурси?O(nlnn)

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

Наприклад, наївне сортування злиття є найгіршим випадком і стабільним, але використовує додатковий простір. Стандартний кваксорт може бути стабільним, діє, але в гіршому випадку . Гіпсорт є на місці, в гіршому випадку але не є стабільним. У Вікіпедії є хороша діаграма, які алгоритми сортування мають які недоліки. Зауважте, що не існує алгоритму сортування, який вони перераховують, який має всі три умови стабільності, найгірший випадок і який існує.O(nlnn)O(n)O(n2)O(nlnn)O(nlnn)

Я знайшов документ "Практичний місцевий злиття" Катаджайнена, Пасанена і Теухола, який стверджує, що має найгірший випадок стабільний варіант злиття. Якщо я правильно розумію їхні результати, вони використовують ("знизу вгору?") Об'єднання рекурсивно на першому масиві та останньому масиву, а використовують другому як місця для подряпин для злиття. Я все ще читаю це, тому більше оцінюється будь-яка інформація про те, чи правильно витлумачую їх результати.O(nlnn)141214

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

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


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

1
Дивіться це запитання на math.stackexchange.com.
Цуйосі Іто

Чому різний спосіб вибору стрижня в QuickSort зруйнує його стабільність?
svick

@svick, єдиний спосіб, яким я знаю, як зробити QuickSort найгіршим випадком - це вибрати обертання більш розумним, ніж випадковим. Я навчився це робити за допомогою алгоритму вибору, який використовує алгоритм медіани медіани, який руйнує стабільність. Якщо я щось пропустив, будь ласка, дайте мені знати. O(nlnn)
user834

@TsuyoshiIto, подумайте, як зробити це відповіддю. Крім того, якщо ви можете дати короткий ескіз алгоритму, я думаю, що це також було б корисно.
user834

Відповіді:


6

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

Напевно, найприємнішим є клас алгоритмів під назвою Block sort , включаючи версію (звану WikiSort) Кімом та Кутцнером у 2008 році. Він не тільки стабільний і повністю на місці (O (1) накладні витрати в трансдихотомічній моделі), він є також адаптивним, і, таким чином, буде робити менше кроків для сортування майже відсортованих списків, переходячи до порівнянь O (n) у випадку вже відсортованого списку. Ви можете знайти реалізацію в C, C ++ та Java тут: https://github.com/BonzaiThePenguin/WikiSort

Цікавим є також алгоритм GrailSort (також сортування блоків) Хуанга та Ленґстона (1989-1992), який фактично перевершує WikiSort у кількох типах тестових випадків. Тут доступна реалізація C ++: https://github.com/Mrrl/GrailSort


8

Ви можете написати на місці стабільний злиття. Побачити це див. Власними словами автора:

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

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


8
O(lnn)O(1)O(lnn)

Кнут вирішує це також і в TAoCP.
Рафаель

O(nln2n)

1

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

lg(N!)N1 ), але настільки ж швидкий, як попередні високоналагоджені зразки Python, або гібрид на випадкових масивах.

[...]

Злиття сусідніх прогонів довжиною A і B на місці дуже важко . Відомо теоретичні конструкції, які можуть це зробити, але вони надто складні і повільні для практичного використання . Але якщо у нас тимчасова пам’ять дорівнює min (A, B), це легко.

Джерело: bugs.python.org , автор: Тім Петерс

O(nlogn) найгіршим сортом часу злиття складності.

Також зауважте, що Timsort добре працює на вже відсортованих масивах.

Тож Python використовує Timsort (який є Mergesort з деякими налаштуваннями), і коли я шукав впровадження Java кілька років тому, це був також Mergesort (я думаю, вони зараз також використовують Timsort).

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