Quick Sort
Conceitos do QuickSort
O próximo algoritmo de ordenação de dados que falaremos é o Quick Sort. Assim como o Merge Sort, o Quick Sort é um algoritmo que se baseia no princípio da divisão e conquista, porem ele trabalha de maneira contrária uma vez que a parte mais pesada do algoritmo acontece antes da recursão e não nela.
O algoritmo Quick Sort trabalha ordenando uma sequência qualquer de valores dividindo-a em subsequências menores, aplicando recursão para ordenar cada uma destas subsequências e por fim, concatenando-as novamente em uma sequência idêntica a original, porem, já ordenada.
Divisão – Para uma sequência S
de ao menos dois elementos, basta escolher um elemento x
de S
chamado por pivô. Uma vez feito isso, removemos todos os elementos de S e os alocamos em três novas subsequências, sendo elas:
- Uma subsequência
Me
, composta de elementos menores do quex
. - Uma subsequência
Ig
, composta de elementos iguais ax
. - Uma subsequência
Ma
, composta de elementos maiores do quex
.
Vale lembrar que, caso exista apenas um elemento de valor igual ao de x
, a subsequência Lg
será composta de apenas um elemento.
Recursão – Ordene as sequências Me
e Ma
recursivamente.
Conquista – Recoloque os elementos das subsequências Me
, Ig
e Ma
novamente na sequência S
nesta mesma ordem em que foram mencionados.
QuickSort in-place
Uma das melhores maneiras de se aplica o Quick Sort, é através da metodologia Quick Sort in-place. É dito in-place, pois não necessitará de novas sequências, ou seja, não necessita alocar mais memória.
Para que isto seja possível, iremos no preocupar não somente com a composição de novos vetores, mas sim iremos a partir do pivô comparar todos os elementos do vetor com o pivô de maneira a trocar elementos de posição e deixar o pivô centralizado, ou seja, com elementos menores que ele a sua esquerda e maiores que ele a sua direita, com isso já teremos os três novos vetores.
Para que isso seja possível, adotaremos a seguinte técnica:
- Escolher um elemento
x
do vetor, no caso o primeiro elemento do vetor; - Percorrer o vetor da esquerda para a direita procurando um elemento maior que
x
, e da direita para a esquerda procurando um elemento menor ou igual ax
. Quando este elementos forem encontrados, devemos troca-los de posição; - Trocar
x
com o j-ésimo elemento e devolver a posiçãoj
.
Exemplo:
x = S[p] = 12
4 < 12
? Sim -> incrementar ponteiro…
15 < 12
? Não! -> parar ponteiro…
28 > 12
? Sim -> decrementar ponteiro…
20 > 12
? Sim -> decrementar ponteiro…
6 > 12
? Não! -> parar ponteiro…
Os dois ponteiros pararam, logo os seus elementos devem ser trocados e ambos os ponteiros devem ser incrementados!
Continuando…
7 < 12
? Sim -> incrementar ponteiro…
10 < 12
? Sim -> incrementar ponteiro…
2 < 12
? Sim -> incrementar ponteiro…
1 < 12
? Sim -> incrementar ponteiro…
13 < 12
? Não! -> parar ponteiro…
13 > 12
? Sim -> decrementar ponteiro…
1 > 12
? Não! -> parar ponteiro…
Uma vez que os dois ponteiros se ultrapassaram, o elemento escolhido x
deve ser agora trocado com o elemento da posição j
.
Essa foi a primeira passada percorrendo o vetor, o mesmo processo deve continuar até que o vetor fique completamente ordenado. O código a seguir apresenta como implementar o Quick Sort em Java.
Implementação do QuickSort in-place em Java
Para iniciar o exemplo, vamos criar uma classe QuickSort
:
A classe QuickSort já disponibiliza um método específico para a ordenação de números inteiros, conforme a linha 15 do código.
Note que este método invoca o método private void quickSort(int[] vetor, int inicio, int fim)
, logo vamos a seu código fonte:
Observe que nesta etapa, o algoritmo visa divider o vetor de entrada utilizando o método private int dividir(int[] vetor, int inicio, int fim)
, conforme a linha 32. Nesta etapa de divisão veremos como o algoritmo se comporta para realizar a ordenação a cada etapa desta divisão.
Este trecho de código responsável pela divisão do vetor em função da comparação por base de um vetor, estabelecido pelo elemento inicial do vetor, conforme a linha 63.
Utilizando dois ponteiros, um vindo da esquerda e outro da direita, este algoritmo ao mesmo que divide o vetor em dois novos vetores, estabelece uma ordenação fundamentada no pivô, onde os elementos menores que ele ficarão a sua esquerda e os maiores a sua direita. Quando elementos que não atendam a esta regra são localizados no vetor, estes são trocados pelo método private void trocar(int[] vetor, int i, int j)
, conforme linhas 79 e 84. Vejamos seu código fonte:
Agora, já finalizada a classe QuickSort
, vamos elaborar uma classe de teste para ver o comportamento do algoritmo:
Conteúdos relacionados
- Ordenação de dados com Bubble Sort
- Ordenação de dados com Merge Sort
- Pesquisa sequencial
- Pesquisa binaria