Classificação rápida normal
Encontre uma base de valor base e, em seguida, classifique -a em uma viagem para que os números à esquerda da base sejam menores que a base, e os números à direita da base são maiores ou iguais à base. Em seguida, divida -o em dois subarraias classificando. Recursivo assim.
classe pública Quicksort {public static <t estende comparável <?? Super T >> Void Sort (t [] arr) {sort (arr, 0, arr.length - 1);} public static <t estende comparável <??? Super t >> void classy (t [] arr, int esquerda, int, direita) {if (esquerda> = direita) retornar; int p = partição (arr, esquerda, direita); classificar (arr, esquerda, p - 1); classificar (arr, p + 1, direita);} estática privada <t estende comparável <?? super t >> int partition (t [] arr, int esquerda, int à direita) {t base = arr [esquerda]; int j = esquerda; para (int i = esquerda+1; i <= direita; i ++) {if (base.compareto (arr [i])> 0) {j ++; swap (acr, j, i);}} swap (swap (swap (swap (lintel, esquerda, esquerda, lesão, lesão, j) Classificação} public static void swap (objeto [] arr, int i, int j) {if (i! = j) {objeto temp = arr [i]; arr [i] = arr [j]; arr [j] = temp;}} private static void printarr (objeto [] arr) {for (objeto o: arr) {System.out.print (o); System.out.print ("/t");} System.out.println ();} public static void main (string args []) {Integer [] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6, 6}; Printarr (3, // 6sort (arr); printarr (arr); // 0 1 2 3 4 5 6 7 8 9}}Otimização rápida de classificação: selecione aleatoriamente a base do valor base
Quando a matriz é quase ordenada, o desempenho de ordem rápida é ruim (porque após cada ordem, o tamanho recursivo dos subs esquerda e direita é muito diferente, e é provável que a parte maior atinja o (n^2) no final).
Solução: O valor de referência é selecionado aleatoriamente, em vez de tomar o primeiro número todas as vezes. Isso não será perturbado por "Matrizes quase ordenadas". Mas o desempenho de classificação de "matrizes quase fora de ordem" pode cair um pouco, pelo menos há mais da parte que é trocada antes de classificar. Essa troca não tem sentido em fora da ordem ... existem muitos componentes de "sorte" ...
classe pública Quicksort {public static <t estende comparável <?? Super T >> Void Sort (t [] arr) {sort (arr, 0, arr.length - 1);} public static <t estende comparável <??? Super t >> void classy (t [] arr, int esquerda, int, direita) {if (esquerda> = direita) retornar; int p = partição (arr, esquerda, direita); classificar (arr, esquerda, p - 1); classificar (arr, p + 1, direita);} estática privada <t estende comparável <?? super t >> int partition (t [] arr, int esquerda, int à direita) {// Antes de classificar, deixe o valor de referência ser trocado com um número aleatório. Dessa maneira, o valor de referência é aleatório. // não fará com que a escala recursiva dos lados esquerda e direita seja inconsistente quando a matriz for relativamente ordenada, resultando na pior troca de complexidade do tempo (arr, esquerda, (int) (math.random ()*(direita - esquerda+1)+esquerda); t Base = arr [esquerda]; int j = esquerda; para (Int i esquerda+1; 0) {j ++; swap (arr, j, i);}} swap (arr, esquerda, j); retorna j; // retorna o canto inferior do valor de referência após um tipo mentiroso} public static void swap (objeto [] arr, int i, int j) {if (i! Printarr (objeto [] arr) {for (objeto o: arr) {system.out.print (o); system.out.print ("/t");} system.out.println ();} public static void main (string args []) {integer [] arr = {3, 5, 1, 1, 7, 2, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4). 0 4 6sort (arr); printarr (arr); // 0 1 2 3 4 5 6 7 8 9}}A classificação rápida continua a otimizar: use a classificação de inserção em conjunto
A ordem rápida é reduzir continuamente a escala do problema para resolver subproblemas e requer recursão contínua. No entanto, a recursão é pequena o suficiente e, se essa recursão instável + continuar sendo executada, a eficiência pode não ser muito boa.
Portanto, quando o problema é pequeno e quase ordenado, a classificação de inserção tem um bom desempenho. Muitas vezes, você pode ver esses comentários em Arrays.sort () que vem com Java: "Use a classificação de inserção em minúsculas matrizes", "Classificação de inserção em menores matrizes"
classe pública Quicksort {public static <t estende comparável <?? Super t >> Void Sort (t [] arr) {sort (arr, 0, arr.length - 1, 16);}/*** @param Array ARRAY A ser classificado* @param esquerda perto esquerda* @param feche a direita* @param k quando a classificação rápida* @smats @the sclic @the sclic @tiet* @thiTs* @TiMET* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIMET* estende comparável <? Super t >> Void Sort (t [] arr, int, esquerda, int, int k) {// As horas de escala são classificadas por inserção se (direita - esquerda <= k) {insertionsort (arr, esquerda, direita); retorna;} int p = partition (arr, esquerda, direita); sort (arn, esquerda, p - 1, k); Super t >> INSERTIONSORT VOID (t [] arr, int l, int r) {for (int i = l + 1; i <= r; i ++) {t cur = arr [i]; int j = i-1; para (; <T estende comparável <? super t >> int partitio (t [] arr, int esquerd, int, à direita) {// Antes de classificar, deixe a troca de valor de referência com um número aleatório. Dessa maneira, o valor de referência é aleatório. // não fará com que a escala recursiva dos lados esquerdo e direito seja inconsistente quando a matriz for relativamente ordenada, resultando na pior troca de complexidade do tempo (arr, esquerda, (int) (math.random () * (direita - esquerda + 1) + esquerda); t Base = arr [esquerda]; int j = esquerda; para (If i = esquerda + 1; 0) {j ++; swap (arr, j, i);}} swap (arr, esquerda, j); retorna j; // retorna o canto inferior do valor base após a triagem de mentir} public static void swap (objeto [] arr, int i, int j) {if (i! Printarr (objeto [] arr) {for (objeto o: arr) {system.out.print (o); system.out.print ("/t");} system.out.println ();} public static void main (string args []) {integer [] arr = {3, 5, 1, 1, 7, 2, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4). 0 4 6sort (arr); printarr (arr); // 0 1 2 3 4 5 6 7 8 9}}A classificação rápida continua a otimizar: classificação rápida de mão dupla
Na classificação rápida normal inicial, diz -se que o valor base no lado esquerdo da base é menor que a base, enquanto a base no lado direito é maior ou igual à base. Estes iguais à base se reunirão à direita (ou alterará levemente o relacionamento de tamanho se reunirá à esquerda). Enfim, ele vai se afastar. Quando muitos números são repetidos na matriz, isso levará a uma enorme diferença no tamanho dos dois subs. Neste momento, quero atribuir os números iguais à base aos dois lados da base, em vez de reuni -los.
(Nota: Ao testar o código, é melhor desviar o olhar da parte do tipo de inserção e parecer no meu código abaixo ... caso contrário, quando o volume de dados é menor que k = 16, o tipo de inserção é executado ...)
classe pública Quicksort {public static <t estende comparável <?? Super t >> Void Sort (t [] arr) {sort (arr, 0, arr.length - 1, 16);}/*** @param Array ARRAY A ser classificado* @param esquerda perto esquerda* @param feche a direita* @param k quando a classificação rápida* @smats @the sclic @the sclic @tiet* @thiTs* @TiMET* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIMET* estende comparável <? Super t >> Void Sort (t [] arr, int, esquerda, int, int k) {// insertionsort (arr, esquerda, direita); // return; //} if (esquerda> = direita) return; int p = partition (arr, esquerda, direita); classificação (arr, esquerda, direita); classificação, esquerda, esquerda, p - 1, k); Super t >> INSERTIONSORT VOID (t [] arr, int l, int r) {for (int i = l + 1; i <= r; i ++) {t cur = arr [i]; int j = i-1; para (; <T estende comparável <? super t >> int partitio (t [] arr, int esquerd, int, à direita) {// Antes de classificar, deixe a troca de valor de referência com um número aleatório. Dessa maneira, o valor de referência é aleatório. // não fará com que as escalas recursivas dos lados esquerdo e direito sejam inconsistentes quando a matriz for relativamente ordenada, resultando na pior troca de complexidade do tempo (arr, esquerda, (int) (Math.random () * (direita). 1; // Para o intervalo [esquerda+1 ......... direita] mencionado na linha anterior, eu quero dizer [esquerda+1 ...... i) o intervalo aberto direto fechado esquerdo é menor ou igual à base. int j = direita; // para o intervalo [esquerda+1 ...... direita] mencionado nas duas linhas anteriores, j significa que os valores de (J ...... direita], a esquerda e os intervalos fechados direito são maiores ou iguais à base. Para a esquerda, escaneie o primeiro elemento menor que a base e depois J para lá. Classificação} public static void swap (objeto [] arr, int i, int j) {if (i! = j) {objeto temp = arr [i]; arr [i] = arr [j]; arr [j] = temp;}} private static void printarr (objeto [] arr) {for (objeto o: arr) {System.out.print (o); System.out.print ("/t");} System.out.println ();} public static void main (string args []) {Integer [] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6, 6}; Printarr (3, // 6sort (arr); printarr (arr); // 0 1 2 3 4 5 6 7 8 9}}Continue a otimizar a classificação rápida: duas classificações rápidas não requer troca, use a troca
Quando os dois caminhos acima encontram valores maiores que a base e os valores menores que a base, eles usam o método swap () para trocar. A troca de dois dígitos envolve a operação da terceira temperatura variável, com mais operações de leitura e gravação. Em seguida, use o método de atribuição direta para colocar o menos do que à direita e maior do que à esquerda. Quando eu e J nos encontramos, essa posição é onde a base deve ser colocada. Esta viagem está concluída. Apenas recorrente.
classe pública Quicksort {public static <t estende comparável <?? Super t >> Void Sort (t [] arr) {sort (arr, 0, arr.length - 1, 16);}/*** @param Array ARRAY A ser classificado* @param esquerda perto esquerda* @param feche a direita* @param k quando a classificação rápida* @smats @the sclic @the sclic @tiet* @thiTs* @TiMET* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIMET* estende comparável <? Super t >> Void Sort (t [] arr, int, esquerda, int, int k) {// insertionsort (arr, esquerda, direita); // return; //} if (esquerda> = direita) return; int p = partition (arr, esquerda, direita); classificação (arr, esquerda, direita); classificação, esquerda, esquerda, p - 1, k); Super t >> INSERTIONSORT VOID (t [] arr, int l, int r) {for (int i = l + 1; i <= r; i ++) {t cur = arr [i]; int j = i-1; para (; <T estende comparável <? super t >> int partitio (t [] arr, int esquerd, int, à direita) {// Antes de classificar, deixe a troca de valor de referência com um número aleatório. Dessa maneira, o valor de referência é aleatório. // não fará com que as escalas recursivas dos lados esquerdo e direito sejam inconsistentes quando a matriz for relativamente ordenada, resultando na pior troca de complexidade do tempo (arr, esquerda, (int) (Math.random () * (direita] esquerda + 1) + esquerda); t Base = ARR [Arr]; Esquerda; // para o intervalo [esquerda+1 ......... direita] mencionado na linha anterior, eu quero dizer [esquerda+1 ...... i) Os valores de intervalo fechado à esquerda são menores ou iguais à base. int j = direita; // para o intervalo [esquerda+1 ...... direita] mencionado nas duas linhas anteriores, J significa que os valores de (J ...... os intervalos de esquerda e encerrados da esquerda são maiores ou iguais a base. j-; arr [i] = arr [j]; // Digitam da esquerda para a direita, digitalize o primeiro elemento maior que a base e depois paro por aí. i, int j) {if (i! = j) {objeto temp = arr [i]; arr [i] = arr [j]; arr [j] = temp;}} private static void printarr (object [] arr) {para (objeto o: arr) {system.out.print (o); system.oun ("/t"); args []) {Integer [] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 4, 6}; Printarr (arr); // 3 5 1 7 2 9 8 0 4 6sort (arr); Printarr (arr); // 0 1 2 3 4 5 6 7 8}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}A classificação rápida continua a otimizar: quando uma grande quantidade de dados e muitas repetições são usadas, use classificação rápida de três vias
Divida a matriz em três caminhos. O primeiro caminho é menor que a base, o segundo caminho é igual à base e o terceiro caminho é maior que a base.
Use um ponteiro para digitalizar de frente para trás, se:
1. O número apontado por curs é menor que a base, então: troca os valores de arr [cur] e arr [i] e depois i ++, cur ++.
2. O número apontado por curs é igual à base, então: cur ++
3. O número apontado por curs é maior que a base, então: troca os valores de arr [cur] e arr [j] e depois j--.
Quando Cur> J, significa que todos os três caminhos foram concluídos.
classe pública Quicksort {public static <t estende comparável <?? Super t >> Void Sort (t [] arr) {sort (arr, 0, arr.length - 1, 16);}/*** @param Array ARRAY A ser classificado* @param esquerda perto esquerda* @param feche a direita* @param k quando a classificação rápida* @smats @the sclic @the sclic @tiet* @thiTs* @TiMET* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIPO* @TIMET* estende comparável <? Super t >> Void Sort (t [] arr, int, esquerda, int, int k) {// insertionsort (arr, esquerda, direita); // return; //} if (esquerda> = direita) return; int [] ret = partition (arr, esquerda, direita); classificar (arr, esquerda, [0], k); rat (ret [1], esquerda, direita); Sort (arn, esquerda, esquerda, [0], k); rat (re ret [1], 1; super t >> void insertionsort (t [] arr, int l, int r) {for (int i = l + 1; i <= r; i ++) {t cur = arr [i]; int j = i-1; para (; j> = 0 && cur.compareTo (arr.r [j]) <0; j-) {[j + 1] @param prtay a ser classificado* @param deixou o limite esquerdo da matriz a ser classificado* @param o limite direito da matriz a ser classificado* @param <t> genéricos* @return*/private static <t estende comparável <?? super t >> int [] partição (t [] arr, int esquerd, int direita) {// Antes de classificar, deixe o valor de referência ser trocado com um número aleatório. Dessa maneira, o valor de referência é aleatório. // não fará com que as escalas recursivas nos lados esquerdo e direito sejam inconsistentes quando a matriz for relativamente ordenada, resultando na pior troca de complexidade do tempo (arr, esquerda, (int) (math.random () * (direita à esquerda + 1) + esquerda); Base T = ARR [esquerda]; Dividido nos três canais a seguir (intervalos) int i = esquerda; // esquerda indica que [Lleft ... esquerda) os números na esquerda fechada intervalo aberto direito são menores que a base int j = direita; // esquerda indica que (RIright ... RIRETO] os números do lado esquerdo e direito fechados ... são maiores que o curto da base), a base direita e à direita. j) {if (arr [cur] .compareto (base) == 0) {cur ++;} else if (arr [cur] .compareto (base) <0) {swap (arr, curs ++, i ++);} else {swap (arr, j-);}}} retorn {]; i-1; 1; 1; 1; O Sub-Problema precisa apenas resolver a esquerda e a direita de i e j} public static void Swap (objeto [] arr, int i, int j) {if (i! = j) {objeto temp = arr [i]; arr [i] = arr [j]; arr [] = temp;}} o estático privado void Printarr (objeto [] {System.out.print (o); System.out.print ("/t");} System.out.println ();} public static void main (string args []) {Integer [] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6, 6}; Printarr (3, // 6sort (arr); printarr (arr); // 0 1 2 3 4 5 6 7 8 9}}Resumir
O exposto acima é toda a explicação detalhada da implementação de programação Java. Espero que seja útil para todos. Amigos interessados podem continuar se referindo a outros tópicos relacionados neste site. Se houver alguma falha, deixe uma mensagem para apontá -la. Obrigado amigos pelo seu apoio para este site!