Classificação rápida em Java explicada

Quick Sort Java Explained



Quick Sort, também escrito como Quicksort, é um esquema de classificação de lista que usa o paradigma dividir para conquistar. Existem diferentes esquemas de classificação rápida, todos usando o paradigma dividir para conquistar. Antes de explicar a Classificação rápida, o leitor deve conhecer a convenção para reduzir pela metade uma lista ou sublista e a mediana de três valores.

Convenção de redução pela metade

Quando o número de elementos em uma lista é par, dividir a lista pela metade significa que a primeira metade literal da lista é a primeira metade, e a segunda metade literal da lista é a segunda metade. O elemento do meio (meio) de toda a lista é o último elemento da primeira lista. Isso significa que o índice do meio tem comprimento / 2 - 1, pois a contagem do índice começa do zero. Comprimento é o número de elementos na lista. Por exemplo, se o número de elementos for 8, a primeira metade da lista terá 4 elementos e a segunda metade da lista também terá 4 elementos. Está bem. Como a contagem do índice começa em 0, o índice do meio é 3 = 8/2 - 1.







E quanto ao caso, quando o número de elementos na lista ou sublista é ímpar? No início, o comprimento ainda é dividido por 2. Por convenção, o número de elementos na primeira metade dessa divisão é comprimento / 2 + 1/2. A contagem do índice começa do zero. O índice do meio é dado por comprimento / 2 - 1/2. Este é considerado o meio termo, por convenção. Por exemplo, se o número de elementos em uma lista for 5, o índice do meio será 2 = 5/2 - 1/2. E, há três elementos na primeira metade da lista e dois elementos na segunda metade. O elemento do meio de toda a lista é o terceiro elemento no índice, 2, que é o índice do meio porque a contagem do índice começa em 0.



A divisão dessa forma é um exemplo de aritmética de inteiros.



Mediana de três valores

Pergunta: Qual é a mediana da sequência:





C B A

Solução:
Organize a lista em ordem crescente:



A B C

O termo do meio, B, é a mediana. É a magnitude que se encontra entre as outras duas magnitudes.

Procurar a mediana em uma lista não é desse tipo. Por exemplo, em uma lista de 19 elementos não classificados, a mediana para o primeiro elemento, o elemento do meio e o último elemento podem ser necessários. Esses três valores podem não estar em ordem crescente; e assim, seus índices devem ser levados em consideração.

Com a Classificação rápida, a mediana de toda a lista e das sublistas é necessária. O pseudocódigo para procurar a mediana de três valores espaçados em uma lista (matriz) é:

meio: =(baixo+Alto) / 2
E searr[meio] <arr[baixo]
troca de chegada[baixo]com arr[meio]
E searr[Alto] <arr[baixo]
troca de chegada[baixo]com arr[Alto]
E searr[meio] <arr[Alto]
troca de chegada[meio]com arr[Alto]
pivô: =arr[Alto]

O termo arr significa array. Este segmento de código procura a mediana e também faz alguma classificação. Este segmento de código parece simples, mas pode ser bastante confuso. Portanto, preste atenção à seguinte explicação:

A classificação neste tutorial produzirá uma lista em que o primeiro valor é o menor valor e o último valor é o maior. Com o alfabeto, A é menor que Z.

Aqui, o pivô é a mediana resultante. Baixo é o índice mais baixo da lista ou sublista (não necessariamente para o valor mais baixo); high é o índice mais alto da lista ou sublista (não necessariamente para o valor mais alto) e middle é o índice do meio convencional (não necessariamente para o valor do meio de toda a lista).

Portanto, a mediana a ser obtida está entre o valor do índice mais baixo, o valor do índice do meio e o valor do índice mais alto.

No código, o índice médio convencional é obtido primeiro. Neste início, a lista não está classificada. A comparação e algum rearranjo em ordem crescente dos três valores devem ocorrer ao mesmo tempo. A primeira instrução if compara o valor do índice mais baixo e do índice do meio. Se o índice do meio for menor do que o índice mais baixo, os dois valores trocam de posição. Isso inicia a classificação e altera a organização dos valores na lista ou sub-lista. A segunda instrução if compara o valor do índice mais alto com o do índice mais baixo. Se o índice mais alto for menor que o índice mais baixo, os dois valores trocam de posição. Isso leva a alguma classificação e alteração da organização dos valores na lista ou sub-lista. A terceira instrução if compara o valor do índice do meio e do índice mais alto. Se aquele do índice mais alto for menor do que o índice do meio, os dois valores trocam de posição. Alguma classificação ou reorganização também pode ocorrer aqui. Esta terceira condição se não é como as duas anteriores.

Ao final dessas três trocas, o valor médio dos três valores em questão seria A [alto], cujo conteúdo original pode ter sido alterado no segmento de código. Por exemplo, considere a sequência não classificada:

C B A

Já sabemos que a mediana é B. Porém, isso deve ser comprovado. O objetivo aqui é obter a mediana desses três valores usando o segmento de código acima. A primeira instrução if compara B e C. Se B for menor que C, então as posições de B e C devem ser trocadas. B é menor que C, então o novo arranjo se torna:

B C A

Observe que os valores para o índice mais baixo e o índice do meio mudaram. A segunda instrução if compara A e B. Se A for menor que B, então as posições de A e B devem ser trocadas. A é menor que B, então o novo arranjo se torna:

A C B

Observe que os valores do índice mais alto e do índice mais baixo mudaram. A terceira instrução if compara C e B. Se C for menor que B, as posições de C e B devem ser trocadas. C não é menor que B, então nenhuma troca ocorre. O novo arranjo permanece como o anterior, ou seja:

A C B

B é a mediana, que é, A [alto], e é o pivô. Portanto, o pivô nasce no final da lista ou sublista.

A função de troca

Outro recurso necessário para a Classificação rápida é a função de troca. A função de troca, troca os valores de duas variáveis. O pseudocódigo para a função de troca é:

definir troca(x,e)
temp: =x
x: =e
e: =temp

Aqui, xey referem-se aos valores reais e não às cópias.

A classificação neste artigo produzirá uma lista em que o primeiro valor é o menor valor e o último valor é o maior.

Conteúdo do Artigo

Algoritmo de classificação rápida

A maneira normal de classificar uma lista não classificada é considerar os dois primeiros valores. Se não estiverem em ordem, coloque-os em ordem. Em seguida, considere os três primeiros valores. Faça a varredura dos dois primeiros para ver onde o terceiro valor se encaixa e se ajusta apropriadamente. Em seguida, considere os primeiros quatro valores. Faça a varredura dos três primeiros valores para ver onde o quarto valor se encaixa e se ajusta apropriadamente. Continue com este procedimento até que toda a lista seja classificada.

Este procedimento, também conhecido como tipo de força bruta, no jargão da programação de computadores, é muito lento. O algoritmo Quick Sort vem com um procedimento muito mais rápido.

As etapas para o algoritmo de classificação rápida são as seguintes:

  1. Certifique-se de que haja pelo menos 2 números para classificar na lista não classificada.
  2. Obtenha um valor central estimado para a lista, denominado pivô. A mediana, conforme descrito acima, é uma forma de obter o pivô. Diferentes maneiras vêm com suas vantagens e desvantagens. - Veja mais tarde.
  3. Particione a lista. Isso significa que coloque o pivô na lista. Desta forma, todos os elementos da esquerda são menores que o valor do pivô e todos os elementos da direita são maiores ou iguais ao valor do pivô. Existem diferentes maneiras de particionar. Cada método de partição vem com suas vantagens e desvantagens. Particionar é dividir no paradigma dividir para conquistar.
  4. Repita as etapas 1, 2 e 3 recursivamente para os novos pares de sublistas que surgem até que toda a lista seja classificada. Isso é uma conquista no paradigma de dividir e conquistar.

O pseudocódigo Quick Sort é:

algoritmo quicksort(arr,baixo,Alto)é
E sebaixo<alto então
pivô(baixo,Alto)
p: =partição(arr,baixo,Alto)
ordenação rápida(arr,baixo,p- 1)
ordenação rápida(arr,p+ 1,Alto)

Um Pseudocódigo de Partição

O pseudocódigo de partição usado neste tutorial é:

partição de algoritmo(arr,baixo,Alto)é
pivô: =arr[Alto]
eu: =baixo
j: =Alto
Faz
Faz
++eu
enquanto(arr[eu] <pivô)
Faz
-j
enquanto(arr[j] >pivô)
E se (eu<j)
troca de chegada[eu]com arr[j]
enquanto(eu<j)
troca de chegada[eu]com arr[Alto]
Retornaeu

Na ilustração de classificação rápida abaixo, este código é usado:

Ilustração de classificação rápida

Considere a seguinte lista não classificada (matriz) de letras alfabéticas:

Q W E R T Y U I O P

Por inspeção, a lista classificada é:

E I O P Q R T U W Y

A lista classificada será agora comprovada, usando o algoritmo acima e segmentos de pseudocódigo, a partir da lista não classificada:

Q W E R T Y U I O P

O primeiro pivô é determinado a partir de arr [0] = Q, arr [4] = T e arr [9] = P, e é identificado como Q e colocado na extremidade direita da lista. Portanto, a lista com qualquer classificação de função dinâmica torna-se:

P W E R T Y U I O Q

O pivô atual é Q. O procedimento de pivô fez uma pequena classificação e colocou P na primeira posição. A lista resultante deve ser reorganizada (particionada), de modo que todos os elementos à esquerda sejam menores em valor, então o pivô e todos os elementos à direita do pivô são iguais ou maiores que o pivô. O computador não pode fazer o particionamento por inspeção. Então, ele faz usando os índices e o algoritmo de partição acima.

Os índices baixo e alto agora são 0 e 9. Portanto, o computador começará a escanear a partir do índice 0 até atingir um índice, cujo valor é igual ou maior que o pivô e para aí temporariamente. Ele também fará a varredura da extremidade superior (direita), índice 9, descendo, até atingir um índice cujo valor é menor ou igual ao pivô e para aí temporariamente. Isso significa duas posições de parada. Se i, a variável de índice incremental, de baixo ainda não for igual ou maior que a variável de índice decrescente, de alto, então esses dois valores são trocados. Na situação atual, a varredura de ambas as extremidades parou em W e O. Assim, a lista se torna:

P O E R T Y U I W Q

O pivô ainda é Q. A varredura em direções opostas continua e pára de acordo. Se i ainda não for igual ou maior que j, os dois valores nos quais a varredura de ambas as extremidades foi interrompida serão trocados. Desta vez, a varredura de ambas as extremidades parou em R e I. Assim, a organização da lista torna-se:

P O E I TY U R W Q

O pivô ainda é Q. A varredura em direções opostas continua e pára de acordo. Se i ainda não for igual ou maior que j, os dois valores nos quais a varredura foi interrompida serão trocados. Desta vez, a varredura de ambas as extremidades parou em T para i e I para j. eu e j se encontraram ou se cruzaram. Portanto, não pode haver troca. A lista permanece a mesma:

P O E I TY U R W Q

Neste ponto, o pivô, Q, deve ser colocado em sua posição final na classificação. Isso é feito trocando arr [i] com arr [high], trocando T e Q. A lista se torna:

P O E I Q Y U R W T

Neste ponto, o particionamento de toda a lista terminou. O pivô = Q cumpriu seu papel. Existem agora três sublistas, que são:

P O E I Q Y U R W T

A partição é divisão e conquista (classificação) no paradigma. Q está em sua posição de classificação correta. Cada elemento à esquerda de Q é menor que Q, e cada elemento à direita de Q é maior que Q. No entanto, a lista da esquerda ainda não está classificada; e a lista certa ainda não foi classificada. Toda a função Quick Sort deve ser chamada recursivamente para classificar a sub-lista esquerda e a sub-lista direita. Esta recuperação da Classificação Rápida deve continuar; novas sublistas serão desenvolvidas até que toda a lista original esteja completamente classificada. Para cada chamada da função Quick Sort, a sub-lista à esquerda é atendida primeiro, antes que a sub-lista à direita correspondente seja atendida. Um novo pivô deve ser obtido para cada sublista.

Para a sublista:

P O E I

O pivô (mediana) para P, O e I é determinado. O pivô seria O. Para esta sub-lista, e em relação à lista completa, o novo arr [baixo] é arr [0] e o novo arr [alto] é o último arr [i-1] = arr [ 4-1] = arr [3], onde i é o índice pivô final da partição anterior. Depois que a função pivot () for chamada, o novo valor pivô, pivô = O. Não confunda entre a função pivô e o valor pivô. A função pivô pode fazer uma pequena classificação e colocar o pivô na extrema direita da sub-lista. Esta sub-lista torna-se,

I P E O

Com este esquema, o pivô sempre termina na extremidade direita da sublista ou lista após sua chamada de função. A varredura de ambas as extremidades começa em arr [0] e arr [3] até que i e j se encontrem ou se cruzem. A comparação é feita com pivô = O. As primeiras paradas estão em P e E. Elas são trocadas, e a nova sub-lista torna-se:

I E P O

A varredura de ambas as extremidades continua, e as novas paradas são em P para i e em E para j. Agora eu e j nos encontramos ou nos cruzamos. Portanto, a sublista permanece a mesma que:

I E P O

O particionamento de uma sublista ou lista termina quando o pivô é colocado em sua posição final. Portanto, os novos valores para arr [i] e arr [high] são trocados. Ou seja, P e O são trocados. A nova sub-lista torna-se:

I E O P

O está agora em sua posição final para toda a lista. Seu papel de pivô acabou. A sublista está atualmente particionada em mais três listas, que são:

I E O P

Neste ponto, a classificação rápida da primeira sub-lista à direita deve ser chamada. No entanto, ele não será chamado. Em vez disso, será anotado e reservado para ser chamado mais tarde. Conforme as instruções da função de particionamento estavam sendo executadas, do topo da função, é a Classificação Rápida para a sub-lista esquerda que deve ser chamada agora (após pivot () ter sido chamado). Será chamado para a lista:

I E

Ele começará procurando a mediana de I e E. Aqui, arr [low] = I, arr [mid] = I e arr [high] = E. Portanto, a mediana, pivô, deve ser determinada pelo algoritmo de pivô como , I. No entanto, o pseudocódigo de pivô acima determinará o pivô como E. Este erro ocorre aqui porque o pseudocódigo acima se destina a três elementos e não a dois. Na implementação abaixo, há alguns ajustes no código. A sub-lista torna-se,

E eu

O pivô sempre termina na extremidade direita da sublista ou lista após sua chamada de função. A varredura de ambas as extremidades começa em arr [0] e arr [1] exclusivo até i e j se encontrarem ou cruzarem. A comparação é feita com pivô = I. As primeiras e únicas paradas são em I e E: em I para i e em E para j. Agora eu e j nos encontramos ou cruzamos. Portanto, a sublista permanece a mesma que:

E eu

O particionamento de uma sublista ou lista termina quando o pivô é colocado em sua posição final. Portanto, os novos valores para arr [i] e arr [high] são trocados. Acontece aqui que arr [i] = I e arr [high] = I. Portanto, o mesmo valor é trocado por ele mesmo. A nova sub-lista torna-se:

E eu

I está agora em sua posição final para toda a lista. Seu papel de pivô acabou. A sub-lista agora está particionada em mais duas listas, que são,

E eu

Agora, os pivôs até agora foram Q, O e I. Os pivôs terminam em suas posições finais. Uma sublista de um único elemento, como o P acima, também termina em sua posição final.

Neste ponto, a primeira sub-lista à esquerda foi completamente classificada. E o procedimento de classificação está agora em:

E I O P Q Y U R W T

A primeira sub-lista certa:

Y U R W T

ainda precisa ser classificado.

Conquistando a primeira sub-lista à direita
Lembre-se de que a chamada de classificação rápida para a primeira sub-lista à direita foi anotada e reservada em vez de executada. Neste ponto, ele será executado. E assim, o novo arr [baixo] = arr [5] = arr [QPivotIndex + 1], e o novo arr [alto] permanece arr [9]. Um conjunto semelhante de atividades que aconteceram para a primeira sub-lista à esquerda acontecerá aqui. E esta primeira sub-lista à direita é classificada em:

R T U W Y

E a lista original não classificada foi classificada para:

E I O P Q R T U W Y

Codificação Java

Colocar o algoritmo em Java é apenas colocar todos os segmentos de pseudocódigo acima em métodos Java em uma classe. Não se esqueça de que deve haver um método main () na classe que chamará a função quicksort () com o array não classificado.

Método pivot ()

O método Java pivot () que retorna o valor, pivot, deve ser:

vaziopivô(Caracteresarr[], intbaixo, intAlto) {
intmeio= (baixo+Alto) / 2;
E se (arr[meio] <arr[baixo])
troca(arr,baixo,meio);
E se (arr[Alto] <arr[baixo])
troca(arr,baixo,Alto);
E se ((Alto-baixo) > 2) {
E se (arr[meio] <arr[Alto])
troca(arr,meio,Alto);
}
}

O método swap ()

O método swap () deve ser:

vaziotroca(Caracteresarr[], intx, inte) {
Caracterestemp=arr[x];
arr[x] =arr[e];
arr[e] =temp;
}

Método quicksort ()

O método quicksort () deve ser:

vazioordenação rápida(Caracteresarr[], intbaixo, intAlto) {
E se (baixo<Alto) {
pivô(arr,baixo,Alto);
intp=partição(arr,baixo,Alto);
ordenação rápida(arr,baixo,p- 1);
ordenação rápida(arr,p+ 1,Alto);
}
}

Método de partição ()

O método partition () deve ser:

intpartição(Caracteresarr[], intbaixo, intAlto) {
Caracterespivô=arr[Alto];
inteu=baixo;
intj=Alto;
Faz {
Faz
++eu;
enquanto(arr[eu] <pivô);
Faz
-j;
enquanto(arr[j] >pivô);
E se (eu<j)
troca(arr,eu,j);
}enquanto(eu<j);
troca(arr,eu,Alto);
Retornaeu;
}

O método main ()

O método main () pode ser:

públicoestático vazioa Principal(Fragmento[]args) {
Caracteresarr[] = {'Q', 'NO', 'E', 'R', 'T', 'E', 'VOCÊ', 'EU', 'OU', 'P'};
TheClass QuickSort= novoA classe();
Ordenação rápida.ordenação rápida(arr, 0, 9);
Sistema.Fora.println('Os elementos classificados:');
para(inteu=0;eu<10;eu++) {
Sistema.Fora.imprimir(arr[eu]);Sistema.Fora.imprimir('');
}
Sistema.Fora.println();
}

Todos os métodos acima podem ser colocados em uma classe.

Conclusão

O Quick Sort é um algoritmo de classificação que usa o paradigma dividir e conquistar. Ele começa dividindo uma lista não classificada em duas ou três sublistas. Neste tutorial, o Quick Sort dividiu uma lista em três sublistas: uma sublista esquerda, uma lista intermediária de um único elemento e uma sublista direita. Conquistar na Classificação Rápida é dividir uma lista ou sub-lista enquanto a classifica, usando um valor pivô. Este tutorial explicou uma implementação da Classificação rápida na linguagem de computador Java.

Sobre o autor

Chrysanthus Forcha

Descobridor da integração matemática dos primeiros princípios e séries relacionadas. Mestre em Educação Técnica, com especialização em Eletrônica e Softwares. BSc Electronics. Também tenho conhecimento e experiência em nível de Mestrado em Computação e Telecomunicações. De 20.000 escritores, fui o 37º melhor escritor do devarticles.com. Trabalho nessas áreas há mais de 10 anos.

Ver todas as postagens

POSTAGENS DE DICAS DO LINUX RELACIONADAS