Algoritmo de Ordenação
- Algoritmos de Ordenação Comuns
- ordenação rápida
-
- 1. Introdução
- 2. Análise do Pensamento
- 3. Diagrama
-
- 3.1 início
- 3.2 Encontre um número menor que o benchmark da direita para a esquerda
- 3.3 Pare à direita, procure um número maior que o benchmark da esquerda para a direita
- 3.4 Troque os números correspondentes a L e R
- 3.5 Continuação do método acima
- 3.6 Lidando com os números à esquerda
- 3.7 Processando os números à direita
- 4. Implementação do código
- classificação de mesclagem
- classificação radix
Algoritmos de Ordenação Comuns
ordenação rápida
1. Introdução
Quicksort é um algoritmo de ordenação desenvolvido por Tony Hall. Em média, classificar n itens requer O(nlogn) comparações. No pior caso, comparações Ο(n2) são necessárias, mas isso não é comum. Na verdade, o quicksort geralmente é significativamente mais rápido do que outros algoritmos Ο(nlogn) porque seu loop interno pode ser implementado de forma eficiente na maioria das arquiteturas.
O Quicksort usa uma estratégia de dividir e conquistar para dividir uma lista em duas sublistas.
A classificação rápida é outra aplicação típica da ideia de dividir e conquistar em algoritmos de classificação. Em essência, a ordenação rápida deve ser considerada como um método recursivo de dividir e conquistar baseado na ordenação por bolhas.
O nome Quick Sort é simples e grosseiro, pois assim que você ouve o nome já sabe o significado de sua existência, que é rápida e eficiente! É um dos algoritmos de classificação mais rápidos para big data. Embora a complexidade de tempo do Pior Caso atinja O(n²), eles são excelentes e, na maioria dos casos, têm desempenho melhor do que algoritmos de ordenação com uma complexidade de tempo média de O(n logn).
O pior caso de execução de classificação rápida é O(n²), como a classificação rápida de matrizes sequenciais. Mas seu tempo esperado amortizado é O(nlogn), e o fator constante implícito na notação O(nlogn) é pequeno, muito menor do que o merge sort cuja complexidade é estável em O(nlogn). Portanto, para a grande maioria das sequências de números aleatórios com ordem mais fraca, a classificação rápida é sempre melhor do que a classificação por mesclagem.
2. Análise do Pensamento
O algoritmo de classificação rápida implementa a classificação por meio de múltiplas comparações e trocas, e seu processo de classificação é o seguinte:
(1) Primeiro, defina um valor de corte e divida a matriz em partes esquerda e direita até o valor de corte.
(2) Colete os dados maiores ou iguais ao valor de corte à direita da matriz e colete os dados menores que o valor de corte à esquerda da matriz. Neste momento, cada elemento na parte esquerda é menor que o valor de corte e cada elemento na parte direita é maior ou igual ao valor de corte.
(3) Em seguida, os dados esquerdo e direito podem ser classificados independentemente. Para os dados da matriz no lado esquerdo, um valor de limite pode ser obtido para dividir essa parte dos dados em partes esquerda e direita, e o valor menor é colocado no lado esquerdo e o valor maior é colocado no lado direito. Os dados da matriz à direita também podem ser processados de forma semelhante.
(4) Repita o processo acima, pode-se ver que esta é uma definição recursiva. Depois de classificar a parte esquerda por recursão, classifique recursivamente a ordem da parte direita. Quando a classificação dos dados nas partes esquerda e direita é concluída, a classificação de toda a matriz também é concluída.
3. Diagrama
3.1 início
Comece de ambas as extremidades da matriz arr, respectivamentedetecção. Primeiro encontre um número menor que 8 da direita para a esquerda, depois encontre um número maior que 8 da esquerda para a direita e depois troque-os. Aqui você pode usar duas variáveis L (esquerda) e R (direita), que apontam para o extremo esquerdo e o extremo direito da sequência, respectivamente. No início, deixe L apontar para a extrema esquerda da matriz, apontando para o número 8. Deixe R apontar para a extrema direita da matriz, apontando para o número 11.
3.2 Encontre um número menor que o benchmark da direita para a esquerda
3.3 Pare à direita, procure um número maior que o benchmark da esquerda para a direita
3.4 Troque os números correspondentes a L e R
depois da troca
3.5 Continuação do método acima
O primeiro R começa a despachar. Como o número base definido aqui é o número mais à esquerda, é muito importante deixar R ir primeiro (pense por si mesmo por quê). A sentinela R move-se passo a passo para a esquerda (ou seja, R–-) até encontrar um número menor que 8 e parar. Em seguida, a sentinela L move-se passo a passo para a direita (ou seja, L++) até encontrar um número maior que 8 e parar.
intercâmbio
depois da troca
Neste momento R continua a se mover para a esquerda
Então L se move
Quando L == R, significa que esta posição é a posição de 8, troque
pegar:
Isso conclui a primeira rodada de detecção. Neste momento, o número de referência 8 é usado como ponto de divisão, os números à esquerda de 8 são todos menores ou iguais a 8 e os números à direita de 8 são todos maiores ou iguais a 8. Olhando para trás no processo agora, de fato, a missão de R é encontrar um número menor que o número de referência, e a missão de L é encontrar um número maior que o número de referência até que L e R se encontrem.
3.6 Lidando com os números à esquerda
3.7 Processando os números à direita
pegar:
4. Implementação do código
/**
* 快速排序
* @author 尹稳健~
* @version 1.0
* @time 2022/9/10
*/
public class QuickSort {
public static void main(String[] args) {
int[] arr = {
8, 12, 19, -1, 45, 0, 14, 4, 11};
quickSort(arr,0,arr.length-1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
public static void quickSort(int[] arr,int start, int end){
// 什么时候结束排序?
if (start>end){
return;
}
// 左指针
int L = start;
// 右指针
int R = end;
// 基准
int pivot = arr[start];
// 只要L!=R就继续循环
while (L < R){
// 右边大于基准,从右向左移动
while (L<R && arr[R] >= pivot){
R --;
}
// 左边小于基准,从左向右移动
while (L<R&& arr[L] <= pivot){
L ++;
}
// 说明右边有小于基准的数,左边有大于基准的数,交换
if (L<R){
int temp = arr[L];
arr[L] = arr[R];
arr[R] = temp;
}
}
// L 与 R碰面 找到了 基准的位置
arr[start] = arr[L];
arr[L] = pivot;
// 左边排序
quickSort(arr,start,R-1);
// 右边排序
quickSort(arr,L+1,end);
}
}
Classificação rápida Este artigo está bem escrito, você pode consultar a escrita e compreensão da classificação rápida de outras pessoas
classificação de mesclagem
1. Introdução
Merge sort é um algoritmo de classificação eficaz e estável baseado na operação de mesclagem.Este algoritmo é uma aplicação muito típica de dividir e conquistar (Divide and Conquer). Combine as subsequências ordenadas para obter uma sequência completamente ordenada; isto é, primeiro faça cada subsequência em ordem e depois faça os segmentos da subsequência em ordem. Mesclar duas listas classificadas em uma lista classificada é chamado de mesclagem bidirecional.
2. Análise do Pensamento
Merge sort usa a ideia de dividir e conquistar, e a dificuldade é governar
- Solicite espaço para que seu tamanho seja a soma das duas sequências classificadas, que é usado para armazenar a sequência mesclada
- em primeiro lugarsequência de decomposição, decompõe a sequência nas sequências em cada grupoA quantidade é 1e, em seguida, execute uma classificação por mesclagem
- configurardois ponteiros, as posições iniciais são as posições iniciais das duas sequências classificadas
- Compare os elementos apontados pelos dois ponteiros, selecione o elemento relativamente pequeno e coloque-o no espaço de mesclagem e mova o ponteiro para a próxima posição
- Repita a etapa anterior até que um determinado ponteiro chegue ao final da sequência
- Copie todos os elementos restantes de outra sequência diretamente para o final da sequência mesclada
3. Diagrama
3.1 Dividir, decompor todas as sequências
3.2 Comece a classificar e mesclar
Após cada preenchimento, o ponteiro se move um bit
Quando a matriz esquerda não possui elementos, a direita é preenchida diretamente
pegar
4. Implementação do código
/**
* 归并排序
* @author 尹稳健~
* @version 1.0
* @time 2022/9/12
*/
public class MergeSort {
public static void main(String[] args) {
int[] arr = {
1, 5, 6, 3, 2, 8, 7, 4};
int[] temp = new int[arr.length];
mergeSort(arr,0,arr.length-1,temp);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
/** 分解,并合并排序 */
public static void mergeSort(int[] arr,int left ,int right,int[] temp){
if (left<right){
//中间索引
int mid = (left+right)/2;
//向左递归分解
mergeSort(arr,left,mid,temp);
//向右递归分解
mergeSort(arr,mid+1,right,temp);
//合并
merge(arr,left,mid,right,temp);
}
}
/**
* 合并排序
* @param arr 未排序的数组
* @param left 左边有序子数组的初始索引
* @param mid 中间索引
* @param right 右边最大索引
* @param temp 临时数组
*/
public static void merge(int[] arr,int left,int mid,int right,int[] temp){
// 左边指针索引
int leftPoint = left;
// 右边指针索引
int rightPoint = mid+1;
// 临时数据的指针
int tempLeft = 0;
// 两个序列都不为空时
while (leftPoint <= mid && rightPoint <= right){
//如果第一个序列的元素小于第二序列的元素,就将其放入temp中
if (arr[leftPoint] <= arr[rightPoint]){
temp[tempLeft] = arr[leftPoint];
leftPoint++;
tempLeft ++;
}else{
temp[tempLeft] = arr[rightPoint];
rightPoint++;
tempLeft ++;
}
}
// 右序列为空,直接将做序列的所有元素填充进去
while (leftPoint <= mid){
temp[tempLeft] = arr[leftPoint];
leftPoint++;
tempLeft++;
}
// 左序列为空,直接将右序列的所有元素填充进去
while (rightPoint <= right){
temp[tempLeft] = arr[rightPoint];
rightPoint++;
tempLeft++;
}
//将临时数组中的元素放回数组arr中
tempLeft = 0;
leftPoint = left;
while (leftPoint <= right){
arr[leftPoint] = temp[tempLeft];
leftPoint++;
tempLeft++;
}
}
}
classificação radix
1. Introdução
Radix sort (classificação radix) pertence ao "distribution sort", também conhecido como "bucket sort" ou bin sort. Como o nome sugere, ele distribui os elementos a serem classificados por meio de informações parciais de valores-chave para alguns "buckets", em ordem para alcançar o papel de classificação, o método de classificação radix é uma classificação estável e sua complexidade de tempo é O (nlog®m), onde r é a base usada e m é o número de heaps. Em algum ponto, a classificação radix é mais eficiente do que outros tipos de estabilidade.
2. Análise do Pensamento
- Unifique todos os valores a serem comparados (números inteiros positivos) no mesmo comprimento de dígito e números preenchidos com zeros com dígitos mais curtos
- Começando pelo bit mais baixo, classifique-os um por um
- Classificando do dígito mais baixo para o dígito mais alto (dígito de unidades -> dígito de dezenas -> dígito de centenas -> ... -> dígito mais alto) após a classificação ser concluída, a sequência de números torna-se uma sequência ordenada
- O número de dígitos que precisamos para obter o número máximo
- Você pode alterar o número máximo para um tipo String e, em seguida, encontrar seu comprimento
3. Diagrama
Primeiro, deve haver 10 baldes representando [0-9]
3.1 A primeira rodada é colocada no balde de acordo com as unidades
Em seguida, retire-os um por um. Se houver vários elementos em um balde, aquele que entrar primeiro será retirado primeiro.
3.2 A segunda rodada é colocada no balde de acordo com dezenas
Se não houver o dígito das dezenas, adicione 0 na frente do dígito das unidades
3.3 A terceira rodada é colocada no barril de acordo com a posição das centenas
Depois de tirar um por um
3.34 A quarta rodada é colocada no balde de acordo com milhares
Retire-o para obter:
4. Implementação do código
/**
* 基数排序
* @author 尹稳健~
* @version 1.0
* @time 2022/9/13
*/
public class BaseSorted {
public static void main(String[] args) {
int[] arr = {
43, 52, 1, 89, 190};
sort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
public static void sort(int[] arr){
int maxLength = getMaxLength(arr);
// 定义个二维数组桶,存储元素
int[][] bucket = new int[10][arr.length];
// 存储每个桶中有多少个元素
int[] elementCounts = new int[10];
for (int times = 1,step = 1; times < maxLength + 1; times++,step *= 10) {
// 遍历数组,将元素存入桶中
for (int i = 0; i < arr.length; i++) {
// 获取位数上的数
int digits = arr[i] / step % 10;
bucket[digits][elementCounts[digits]] = arr[i];
elementCounts[digits] ++;
}
//将桶中的元素重新放回到数组中
//用于记录应该放入原数组的哪个位置
int index = 0;
for (int i = 0; i < 10; i++) {
// 从桶中按放入顺序依次取出元素,放入原数组
int position = 0;
while ( elementCounts[i] > 0){
arr[index] = bucket[i][position];
position++;
elementCounts[i]--;
index++;
}
}
}
}
/** 获取数组中元素长度最长的长度 */
public static int getMaxLength(int[] arr){
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max ){
max = arr[i];
}
}
return (max + "").length();
}
}