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


10

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

Я придумав три приклади:

[1,2,3,4,5,6,7,8,9,10] - when the array is sorted
[10,9,8,7,6,5,4,3,2,1] - when the array is reversed
[1,1,1,1,1,1,1,1,1,1] - when the array is the same values
[1,1,1,2,2,2,3,3,3,3] - when there are few and unique keys

Наприклад, я не надто впевнений у цьому:

[1,3,5,7,9,10,8,6,4,2]

Отже, що робить масив, з яким у кикспорта виникають труднощі порівняно з тим, де він (майже) ідеальний?


2
Як вибирається стрижень? Ви заявили два способи, коли він не був обраний, але не як він був обраний.
Вінстон Еверт

Будь ласка, надайте найгірший випадок для QuickSort - коли це може статися? на StackOverflow читання. Я також вважаю sorting.at гарною візуалізацією алгоритмів сортування.

@WinstonEwert Pivot вибирається першим елементом.
mrQWERTY

@ Renren29 Я трохи змінив питання, намагаючись перенести його, щоб зосередити увагу на тому, чому у quicksort виникнуть труднощі із заданим масивом, а не шукати приклади масивів (я не хочу, щоб люди давали вам відповіді, [2,1,2,1,2,1,2,1]і це було цілим відповідь). В ідеалі метою цього питання буде та, куди можуть прийти інші люди та дізнатися більше про те, чому (на що є відповідь), а не про приклади (яких існує незліченна кількість).

Ви кепскортите до шматок двох елементів? Тому що реальні реалізації, як правило, використовують простіші сорти для невеликих шматочків. Наприклад, порівняння та обмін є набагато простішим за швидкий вибір за N = 2.
MSalters

Відповіді:


9

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

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

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


Для швидкодіючої середньої складності середня складність становить nlogn, а найгірший випадок - n ^ 2. Причина, яку варто викликати в гіршому випадку, полягає в тому, що це також той випадок, який створює найбільшу глибину рекурсії. Для наївної реалізації глибина рекурсії може бути n, що може спровокувати переповнення стека. Тестування інших екстремальних ситуацій (включаючи кращий випадок) може бути доцільним з подібних причин.


Я бачу, тому стандартне відхилення від середнього дійсно визначає результат розподілу.
mrQWERTY

"... і майже в кожному випадку найгірший випадок насправді поганий, тому його варто перевірити". . Це дискусійно. Коли я дивлюся на цю таблицю: en.wikipedia.org/wiki/… я роблю висновок, що для більшості "хороших" алгоритмів сортування (тобто із середньою O(NlogN)продуктивністю або кращою) найгірші та середні випадки мають однакову складність. Це говорить про те, що зазвичай НЕ варто тестувати для найгірших випадків. (Враховуючи, що тест, ймовірно, O(N)... або гірше.)
Стівен C

@ Renren29: Медіана 3-х опорних значень буде першою або останньою, лише якщо 2 або 3 значення однакові. SD не вступає в це.
david.pfx

@StephenC: Багато «хороших» алгоритмів, у тому числі кваксорт, мають найгірший складність n ^ 2. Але дивіться редагувати.
david.pfx

@ david.pfx - "Деякі" ... ТАК. "Майже кожен" ... НІ.
Стівен С

0

Алгоритм рятується від більшості поганих випадків, використовуючи рандомізований шарнір, виключаючи безперервні елементи, що дорівнюють стрижню при розподілі та несиметричному пошуку. Він шукає вперед елемент, більший або рівний повороту, і шукає назад елемент, менший ніж зведений.
Дякую MichaelT, що асиметричний пошук призначений для вирішення [2,1,2,1,2,1,2,1].

Наступний результат генерується моєю функцією qsort_random (). N = 100 000

usec    call   compare   copy    pattern
80132   62946  1971278   877143  random
47326   57578  1606067   215155  sorted : 0,1,2,3,...,n-1
49927   63578  1628883   338715  sorted in reverse : n-1,n-2,...,2,1,0
55619   63781  1596934   377330  nearly reverse : n-2,n-1,n-4,n-3,...,2,3,0,1
54714   66667  1611454   290392  median-3-killer : n-1,0,1,2,...,n-2
1491    1      99999     4       all values the same : n,n,n,...
1577    1      99999     4       first is higher : n,1,1,1,...
2778    2      156159    10      last is lower : n,n,n,...,n,1
2994    3      199996    100009  a few data : n,...,n,1,...,1
3196    3      199996    50012   zigzag : n,1,n,1,...,n,1
917796  56284  67721985  673356  valley(sawtooth?) : n-1,n-3,...,0,...,n-4,n-2

Більшість випадків швидше, ніж випадкова закономірність. Картина долини - це поганий випадок для більшості виборних центрів.

qsort(3)       usec = 14523   call = 0      compare = 884463    copy = 0
qsort_head()   usec = 138609  call = 99999  compare = 8120991   copy = 1214397
qsort_middle() usec = 664325  call = 99999  compare = 52928111  copy = 1036047
qsort_trad()   usec = 118122  call = 99999  compare = 6476025   copy = 1337523
qsort_random() usec = 295699  call = 58806  compare = 19439952  copy = 732962
qsort_log2()   usec = 66411   call = 63987  compare = 1597455   copy = 944821

qsort_log2 () виходить із поганого випадку, вибираючи зведені елементи log2 (N).
qsort (3) використовують бібліотеку GNU, яка є сортуванням сортування індексів.
qsort_trad () виберіть стрижень у першому, середньому та останньому елементах.
qsort_random () та qsort_log2 () не використовують своп.
Програми та сценарії вихідних програм C розміщуються в github .

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