Académique Documents
Professionnel Documents
Culture Documents
Quicksort
Proposto por C. A. R. Hoare em 1960 e publicado em 1962. o algoritmo de ordenao interna mais rpido que se conhece para uma ampla variedade de situaes. Provavelmente o mais utilizado. A idia bsica dividir o problema de ordenar um conjunto com n itens em dois problemas menores. Os problemas menores so ordenados independentemente. Os resultados so combinados para produzir a soluo final.
Algoritmos e Estrutura de Dados II
Quicksort
O ponto principal do mtodo o processo de partio. O vetor A [Esq..Dir] rearranjado por meio da escolha arbitrria de um piv x. O vetor A particionado em duas partes:
Parte esquerda: chaves x. Parte direita: chaves x.
Algoritmos e Estrutura de Dados II
Quicksort - Partio
Algoritmo para o particionamento:
1. Escolha arbitrariamente um piv x. 2. Percorra o vetor com um ndice i a partir da esquerda at que A[i] x. 3. Percorra o vetor com um ndice j a partir da direita at que A[j] x. 4. Troque A[i] com A[j]. 5. Continue este processo at os apontadores i e j se cruzarem.
Algoritmos e Estrutura de Dados II
Partio - Exemplo
O piv x escolhido como sendo A[(i + j) / 2]. Exemplo: 3 6 4 5 1 7 2
Partio - Exemplo
O piv x escolhido como sendo A[(i + j) / 2]. Exemplo: 3 6 4 5 1 7 2
Piv
3 3 3 3
6 6 2 2
4 4 4 4
5 5 5 1
1 1 1 5
7 7 7 7
2 2 6 6
Resultado final
Quicksort - Partio
void Particao(Indice Esq, Indice Dir, Indice *i, Indice *j, Item *A) { Item x, w; *i = Esq; *j = Dir; x = A[(*i + *j)/2]; /* obtem o pivo x */ do { while (x.Chave > A[*i].Chave) (*i)++; while (x.Chave < A[*j].Chave) (*j)--; if (*i <= *j) { w = A[*i]; A[*i] = A[*j]; A[*j] = w; (*i)++; (*j)--; } } while (*i <= *j); }
Algoritmos e Estrutura de Dados II
6 6
i
4 4
1 1
5 5
7 7
2 2
3
j
Resultado final
Depois da primeira troca, o dice i fica parado no elemento 6 (6 >= piv) enquanto J decrementado at parar no elemento 1, que o prprio piv. Como os ndices se cruzam o procedimento termina
Algoritmos e Estrutura de Dados II
A partio continua ate os ndices se cruzarem, mesmo aps o piv ter movido
6 6
1 1
4 4
5 5
7 7
2 2
Aps a primeira troca, os ndices i e j continuam e param sobre o piv. O piv trocado com ele mesmo e a partio termina com duas partices e mais um elemento (piv) j na posio correta. i j Resultado final
Quicksort
O anel interno da funo de Particao extremamente simples. Razo pela qual o algoritmo Quicksort to rpido.
Quicksort - Funo
/* Entra aqui o procedimento Particao */ void Ordena(Indice Esq, Indice Dir, Item *A) { int i, j; Particao(Esq, Dir, &i, &j, A); if (Esq < j) Ordena(Esq, j, A); if (i < Dir) Ordena(i, Dir, A); } void QuickSort(Item *A, Indice *n) { Ordena(1, *n, A); } Algoritmos e Estrutura de Dados II
Quicksort - Exemplo
3 6 4 5 1 7 2
Quicksort - Exemplo
3
Primeira partio
6 2 2
4 4 4
5 1 3
1 5 5
7 7 7
2 6 6
3 1
Segunda partio
. . .
3 4 5 7 6
Continua...
Algoritmos e Estrutura de Dados II
terceira partio
Quicksort - Exemplo
1
quarta partio
2 2 2
3 4 4
4 1 3
5 5 5
7 6 6
6 7 7
3 1
quinta partio
Final
Quicksort
Caractersticas
Qual o pior caso para o Quicksort? Por que? Qual sua ordem de complexidade? Qual o melhor caso? Por que? Qual sua ordem de complexidade? O algoritmo estvel?
Quicksort
Anlise
Seja C(n) a funo que conta o nmero de comparaes. Pior caso: C(n) = O(n2) O pior caso ocorre quando, sistematicamente, o piv escolhido como sendo um dos extremos de um arquivo j ordenado. Isto faz com que o procedimento Ordena seja chamado recursivamente n vezes, eliminando apenas um item em cada chamada. O pior caso pode ser evitado empregando pequenas modificaes no algoritmo. Para isso basta escolher trs itens quaisquer do vetor e usar a mediana dos trs como piv.
Algoritmos e Estrutura de Dados II
Quicksort
Anlise
Melhor caso: C(n) = 2C(n/2) + n = n log n n + 1 Esta situao ocorre quando cada partio divide o arquivo em duas partes iguais. Caso mdio de acordo com Sedgewick e Flajolet (1996, p. 17): C(n) 1,386n log n 0,846n, Isso significa que em mdia o tempo de execuo do Quicksort O(n log n).
Quicksort
Vantagens:
extremamente eficiente para ordenar arquivos de dados. Necessita de apenas uma pequena pilha como memria auxiliar. Requer cerca de n log n comparaes em mdia para ordenar n itens.
Desvantagens:
Tem um pior caso O(n2) comparaes. Sua implementao muito delicada e difcil:
Um pequeno engano pode levar a efeitos inesperados para algumas entradas de dados.
O mtodo no estvel.
Algoritmos e Estrutura de Dados II
Melhorias no Quicksort
Escolha do piv: mediana de trs
Evita o pior caso
Utilizar um algoritmo simples (seleo, insero) para parties de tamanho pequeno Quicksort no recursivo
Evita o custo de vrias chamadas recursivas
Quicksort no recursivo
void QuickSortNaoRec(Vetor A, Indice n) { TipoPilha pilha; TipoItem item; // campos esq e dir int esq, dir, i, j; FPVazia(&pilha); esq = 0; dir = n-1; item.dir = dir; item.esq = esq; Empilha(item, &pilha);
do if (dir > esq) { { Particao(A,esq,dir,&i, &j); if ((j-esq)>(dir-i)) item.dir = j; item.esq = esq; Empilha(item, &pilha); esq = i; } else { item.esq = i; item.dir = dir; Empilha(item, &pilha); dir = j; } } else { Desempilha(&pilha,&item); dir = item.dir; esq = item.esq; } while (!Vazia(pilha)); }
Exerccio
Execute o quicksort no vetor abaixo indicando qual o piv e os subvetores resultantes de cada partio.
65 77 51 25 03 84 48 21 05