¿Qué lo convierte en un mal caso para la clasificación rápida?

10

Estoy aprendiendo acerca de quicksort y quiero ilustrar diferentes matrices en las que quicksort tendría dificultades. El resumen rápido que tengo en mente no tiene una mezcla aleatoria inicial, hace 2 particiones y no calcula la mediana.

Pensé en tres ejemplos hasta ahora:

[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

Por ejemplo, no estoy muy seguro de esto:

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

Entonces, ¿qué hace que una matriz con la que Quicksort tiene dificultades en comparación con una donde sea (casi) ideal?

mrQWERTY
fuente
2
¿Cómo se selecciona el pivote? Usted indicó dos formas en que no se seleccionó, pero no cómo se seleccionó.
Winston Ewert
Indique el peor caso para QuickSort: ¿cuándo puede ocurrir? en StackOverflow una lectura. También encuentro sorting.at como una buena visualización de los algoritmos de clasificación.
@WinstonEwert Pivot es seleccionado por el primer elemento.
mrQWERTY
@ Renren29 Modifiqué un poco la pregunta tratando de moverla para centrarme en la razón por la cual quicksort tendría dificultades con una matriz determinada en lugar de buscar matrices de ejemplo (no soy gente para darte respuestas [2,1,2,1,2,1,2,1]y eso es todo responder). El objetivo de la pregunta sería, idealmente, que otras personas puedan venir y descubrir más sobre por qué (que tiene una respuesta) en lugar de ejemplos (de los cuales hay innumerables).
¿Estás ejecutando quicksort en trozos de 2 elementos? Debido a que las implementaciones del mundo real tienden a usar tipos más simples para pequeños fragmentos. Por ejemplo, comparar y cambiar es mucho más simple que la clasificación rápida para N = 2.
MSalters

Respuestas:

8

Cada algoritmo de clasificación tiene el peor de los casos, y en muchos casos el peor de los casos es realmente malo, por lo que vale la pena probarlo. El problema es que no existe el peor de los casos solo porque conoces el algoritmo básico.

Los peores casos comunes incluyen: ya ordenados; ordenado en reversa; casi ordenado, un elemento fuera de servicio; todos los valores son iguales; de todos modos, excepto que primero (o último) es más alto (o más bajo). Una vez tuvimos un tipo en el que el peor de los casos era un patrón de diente de sierra en particular, que era muy difícil de predecir pero bastante común en la práctica.

El peor de los casos para quicksort es uno que hace que siempre elija el peor pivote posible, de modo que una de las particiones tenga un solo elemento. Si el pivote es el primer elemento (mala elección), los datos ya ordenados o ordenados inversamente son el peor de los casos. Para una mediana de tres datos dinámicos que son todos iguales o solo el primero o el último es diferente, el truco es el truco.


Para la clasificación rápida, la complejidad promedio es nlogn y el peor de los casos es n ^ 2. La razón por la que vale la pena desencadenar el peor comportamiento es porque este también es el caso que produce la mayor profundidad de recursión. Para una implementación ingenua, la profundidad de recursión podría ser n, lo que puede desencadenar el desbordamiento de la pila. Puede ser útil probar otras situaciones extremas (incluido el mejor de los casos) por razones similares.

david.pfx
fuente
Ya veo, por lo que la desviación estándar de la media realmente determina el resultado de la partición.
mrQWERTY
"... y en casi todos los casos, el peor de los casos es realmente malo, por lo que vale la pena probarlo". . Eso es discutible. Cuando miro esta tabla: en.wikipedia.org/wiki/… Concluyo que para la mayoría de los algoritmos de clasificación "buenos" (es decir, con un O(NlogN)rendimiento promedio o mejor), los casos peores y promedio tienen la misma complejidad. Eso sugiere que generalmente NO vale la pena probar el (los) peor (es) caso (s). (Dado que la prueba es probablemente O(N)... o peor)
Stephen C
@ Renren29: la mediana de 3 pivotes será la primera o la última solo si 2 o 3 de los valores son iguales. SD no entra en eso.
david.pfx
@StephenC: Muchos algoritmos 'buenos', incluido el ordenamiento rápido, tienen n ^ 2 la peor complejidad del caso. Pero ver editar.
david.pfx
@ david.pfx - "Algunos" ... SÍ. "Casi todos" ... NO.
Stephen C
0

Un algoritmo escapa de la mayoría de los casos malos utilizando un pivote aleatorio, excluyendo elementos continuos equivalentes a un pivote de partición y búsqueda asimétrica. Busca hacia adelante un elemento mayor o igual a un pivote, y busca hacia atrás un elemento menor que un pivote.
Agradezco a MichaelT, la búsqueda asimétrica está diseñada para resolver [2,1,2,1,2,1,2,1].

El siguiente resultado es generado por mi función 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

La mayoría de los casos son más rápidos que un patrón aleatorio. El patrón de valle es un mal caso para la mayoría de las selecciones de pivote.

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 () escapa del caso incorrecto seleccionando un pivote en los elementos log2 (N).
qsort (3) usa la biblioteca GNU, que es un tipo de fusión de clasificación de índice.
qsort_trad () selecciona un pivote en los elementos primero, medio y último.
qsort_random () y qsort_log2 () no utilizan el intercambio.
Los programas y scripts de Source C se publican en github .

Leorge Takeuchi
fuente