O que faz com que um caso ruim seja resolvido rapidamente?


10

Estou aprendendo sobre o quicksort e quero ilustrar matrizes diferentes nas quais o quicksort teria dificuldade. O quicksort que eu tenho em mente não possui um embaralhamento aleatório inicial, faz 2 partições e não calcula a mediana.

Pensei em três exemplos até agora:

[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 exemplo, não tenho muita certeza sobre este:

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

Então, o que cria uma matriz com a qual o quicksort tem dificuldade em comparação com uma onde é (quase) ideal?


2
Como o pivô é selecionado? Você declarou duas maneiras pelas quais não foi selecionado, mas não como foi selecionado.
Winston Ewert 23/09

Indique o pior caso para o QuickSort - quando isso pode ocorrer? no StackOverflow uma leitura. Também acho que sorting.at é uma boa visualização dos algoritmos de classificação.

O @WinstonEwert Pivot é selecionado pelo primeiro elemento.
MrQWERTY

@ Renren29 Modifiquei a questão um pouco, tentando movê-la para focar no motivo pelo qual o quicksort teria dificuldade com uma determinada matriz, em vez de procurar matrizes de exemplo (eu não tenho pessoas para lhe dar respostas [2,1,2,1,2,1,2,1]e que é a totalidade responda). O objetivo da pergunta seria, idealmente, aquele em que outras pessoas possam vir e descobrir mais sobre o porquê (que tem uma resposta) e não exemplos (dos quais existem inúmeras).

Você está executando o quicksort em pedaços de 2 elementos? Como as implementações do mundo real tendem a usar tipos mais simples para pequenos pedaços. Por exemplo, comparar e trocar é muito mais simples que o quicksort para N = 2.
precisa saber é o seguinte

Respostas:


8

Todo algoritmo de classificação tem o pior caso e, em muitos casos, o pior é muito ruim, portanto vale a pena testá-lo. O problema é que não existe um pior caso apenas porque você conhece o algoritmo básico.

Os piores casos comuns incluem: já classificados; ordenado ao contrário; quase classificado, um elemento fora de ordem; todos os valores são iguais; todos iguais, exceto o primeiro (ou o último) é mais alto (ou mais baixo). Certa vez, tivemos um tipo em que o pior caso era um padrão de dente de serra específico, que era muito difícil de prever, mas bastante comum na prática.

O pior caso para o quicksort é aquele que sempre escolhe o pior pivô possível, para que uma das partições tenha apenas um elemento. Se o pivô for o primeiro elemento (má escolha), os dados já classificados ou inversos serão o pior caso. Para uma mediana de três dados dinâmicos iguais ou apenas o primeiro ou o último diferentes, o truque.


Para quicksort, a complexidade média é nlogn e o pior caso é n ^ 2. O motivo pelo qual vale a pena desencadear o comportamento do pior caso é porque esse também é o caso que produz a maior profundidade de recursão. Para uma implementação ingênua, a profundidade da recursão pode ser n, o que pode disparar o estouro da pilha. Testar outras situações extremas (incluindo o melhor caso) pode valer a pena por razões semelhantes.


Entendo, então o desvio padrão da média realmente determina o resultado da partição.
MrQWERTY 23/09

"... e em quase todos os casos o pior dos casos é realmente ruim, por isso vale a pena testá-lo." . Isso é discutível. Quando olho para esta tabela: en.wikipedia.org/wiki/… concluo que para a maioria dos algoritmos de classificação "bons" (ou seja, com O(NlogN)desempenho médio ou melhor), os piores e médios casos têm a mesma complexidade. Isso sugere que geralmente NÃO vale a pena testar nos piores casos. (Tendo em conta que o teste é provavelmente O(N)... ou pior.)
Stephen C

@ Renren29: A mediana de 3 pivôs será a primeira ou a última apenas se 2 ou 3 dos valores forem iguais. SD não entra nele.
David.pfx

@ StephenC: Muitos algoritmos 'bons', incluindo quicksort, têm n ^ 2 na pior das complexidades. Mas veja editar.
David.pfx

@ david.pfx - "Alguns" ... SIM. "Quase todo" ... NÃO.
Stephen C

0

Um algoritmo escapa da maioria dos casos ruins usando um pivô aleatório, excluindo elementos contínuos iguais a um pivô do particionamento e da pesquisa assimétrica. Ele pesquisa para frente um elemento maior ou igual a um pivô e pesquisa para trás um elemento menor que um pivô.
Agradeço a MichaelT, a pesquisa assimétrica é planejada para resolver [2,1,2,1,2,1,2,1].

O seguinte resultado é gerado pela minha função 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

A maioria dos casos é mais rápida que um padrão aleatório. O padrão de vale é um caso ruim para a maioria das seleções dinâmicas.

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 () foge de caso incorreto selecionando um pivô nos elementos log2 (N).
O qsort (3) usa a biblioteca GNU, que é uma espécie de mesclagem de classificação de índice.
qsort_trad () seleciona um pivô no primeiro, no meio e no último elemento.
qsort_random () e qsort_log2 () não usam troca.
Os programas e scripts de origem C são publicados no github .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.