Algoritmo de classificação Java detalhado comumente usado (10 tipos)

Os algoritmos de classificação comumente usados ​​em Java são os seguintes:

  1. Tipo de bolha
  2. Classificação de seleção
  3. Ordenação por Inserção
  4. Classificação de shell (classificação de shell)
  5. Mesclar Ordenar
  6. Classificação rápida (Classificação rápida)
  7. Heap Sort
  8. Ordenação por contagem
  9. Ordenação por Balde
  10. Classificação Radix (Classificação Radix)

Esses algoritmos de classificação têm suas próprias vantagens e desvantagens, e o algoritmo apropriado deve ser selecionado de acordo com a situação específica.

1. Classificação de Bolhas

Bubble sort é um algoritmo de classificação simples que percorre repetidamente a matriz a ser classificada, comparando dois elementos por vez e trocando de posição se estiverem na ordem errada. Esse processo continua no final da sequência até que toda a sequência seja classificada.

import org.junit.jupiter.api.Assertions;
import java.util.Arrays;

public class Bubble {
    
    
    public static void bubbleSort(int[] arr) {
    
    
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
    
    
            for (int j = 0; j < n - i - 1; j++) {
    
    
                if (arr[j] > arr[j + 1]) {
    
    
                    // 交换arr[j+1]和arr[j]
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 8, 3, 1, 6};
        int[] expectedArr = {
    
    1, 2, 3, 5, 6, 8};
        Bubble.bubbleSort(arr);
        System.out.println("arr = " + Arrays.toString(arr));
        Assertions.assertArrayEquals(expectedArr, arr);
    }
}

No código acima, a função bubbleSort recebe uma matriz de números inteiros como entrada e a classifica usando o algoritmo de classificação por bolhas. O loop externo é executado n - 1 vezes, onde n é o comprimento da matriz, e o loop interno é executado n - i - 1 vezes, onde i é o número de iteração atual do loop externo. Isso ocorre porque, após cada iteração do loop externo, o maior elemento está definitivamente no final do array, portanto não precisamos compará-lo novamente.

No loop interno, comparamos os elementos adjacentes e os trocamos se não estiverem na ordem correta. Dessa forma, o maior elemento "borbulha" até o final do array. Após cada passagem pelo array, o maior elemento está em sua posição final, então podemos reduzir o tamanho do loop interno em 1.

A complexidade de tempo do Bubble Sort é O(n^2), o que o torna ineficiente para grandes listas e aplicações práticas. No entanto, devido à sua simplicidade, é um bom algoritmo para ensinar ordenação a iniciantes.

2. Classificação de seleção

A ordenação por seleção é um algoritmo de ordenação simples, cuja ideia básica é selecionar o menor (ou maior) elemento dos elementos a serem ordenados a cada vez, e armazená-lo no início da sequência até que todos os elementos a serem ordenados se esgotem.

import org.junit.jupiter.api.Assertions;
import java.util.Arrays;

public class Selection {
    
    
    public static void selectionSort(int[] arr) {
    
    
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
    
    
            int minIndex = i;
            for (int j = i + 1; j < n; j++) {
    
    
                if (arr[j] < arr[minIndex]) {
    
    
                    minIndex = j;
                }
            }
            // 交换arr[i]和arr[minIndex]
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 8, 3, 1, 6};
        int[] expectedArr = {
    
    1, 2, 3, 5, 6, 8};
        Selection.selectionSort(arr);
        System.out.println("arr = " + Arrays.toString(arr));
        Assertions.assertArrayEquals(expectedArr, arr);
    }
}

No código acima, a função selectionSort recebe uma matriz de inteiros como entrada e a classifica usando o algoritmo de classificação por seleção. O loop externo é executado n - 1 vezes, onde n é o comprimento da matriz. No loop interno, encontramos o menor elemento na parte não classificada e armazenamos seu índice na variável minIndex. Em seguida, trocamos o menor elemento pelo final da parte classificada. Após cada iteração do loop externo, o comprimento da parte classificada é aumentado em 1 e o comprimento da parte não classificada é diminuído em 1.

A complexidade de tempo da ordenação por seleção é O(n^2), o que a torna ineficiente para listas grandes e aplicações práticas. No entanto, devido à sua simplicidade, é um bom algoritmo para ensinar ordenação a iniciantes.

3. Ordenação por Inserção

A ordenação por inserção é um algoritmo de ordenação simples, cuja ideia básica é inserir um registro em uma lista ordenada já ordenada para obter uma nova lista ordenada com o número de registros aumentado em 1.

import org.junit.jupiter.api.Assertions;
import java.util.Arrays;

public class Insertion {
    
    
    public static void insertionSort(int[] arr) {
    
    
        int n = arr.length;
        // 外部循环从第二个元素开始,因为我们将第一个元素视为已排序部分
        for (int i = 1; i < n; i++) {
    
    
            int key = arr[i];
            int j = i - 1;
            // 将当前值key和前面的值进行比较,如果前面的值>key 则将值往后移1位
            while (j >= 0 && arr[j] > key) {
    
    
                arr[j + 1] = arr[j];
                j--;
            }
            // 在不小当前值key的位置,插入当前值key
            arr[j + 1] = key;
        }
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 8, 3, 1, 6};
        int[] expectedArr = {
    
    1, 2, 3, 5, 6, 8};
        Insertion.insertionSort(arr);
        System.out.println("arr = " + Arrays.toString(arr));
        Assertions.assertArrayEquals(expectedArr, arr);
    }
}

No código acima, a função insertSort recebe uma matriz de inteiros como entrada e a classifica usando o algoritmo de classificação por inserção. O loop externo começa com o segundo elemento, pois consideramos o primeiro elemento como a parte classificada. No loop interno, comparamos o elemento a ser inserido com o elemento da parte classificada e, se o elemento a ser inserido for menor que o elemento da parte classificada, deslocamos o elemento da parte classificada um bit para a direita para abrir espaço para o elemento a ser inserido. Após o término do loop interno, inserimos o elemento a ser inserido na posição correta. Após cada iteração do loop externo, podemos garantir que os primeiros i elementos foram classificados.

A classificação por inserção tem uma complexidade de tempo de O(n^2), o que a torna ineficiente para listas grandes e aplicações práticas. No entanto, a classificação por inserção é muito simples de implementar e funciona muito bem em listas pequenas.

4. Classificação da casca

A classificação de Hill é um algoritmo de classificação por inserção aprimorado. Sua ideia básica é agrupar a matriz a ser classificada de acordo com um determinado intervalo, classificar cada grupo usando o algoritmo de classificação por inserção, estreitar o intervalo e classificar o agrupamento até que o intervalo seja 1.

O método de redução gradual do tamanho do intervalo ajuda a melhorar a eficiência do processo de classificação, o que pode reduzir o número de comparações e trocas. Esta é uma característica chave do algoritmo Hill sort.

import org.junit.jupiter.api.Assertions;
import java.util.Arrays;

public class Shell {
    
    
    public static void shellSort(int[] arr) {
    
    
        int n = arr.length;
        // 初始化间隔(gap)的值,它决定了每次迭代中子数组的大小
        // 从数组长度的一半开始作为初始间隔值,gap就是分割的子数组数量
        for (int gap = n / 2; gap > 0; gap /= 2) {
    
    
            // 循环从间隔值开始,遍历数组直到数组的末尾;代表循环所有的子数组
            for (int i = gap; i < n; i++) {
    
    
                int temp = arr[i];
                int j = i;
                // 将当前元素 arr[j] 的值替换为前一个元素 arr[j - gap] 的值。
                // 通过这个操作,将较大的元素向后移动,为当前元素腾出位置
                while (j >= gap && arr[j - gap] > temp) {
    
    
                    arr[j] = arr[j - gap];
                    j -= gap;
                }
                arr[j] = temp;
            }
        }
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 8, 3, 1, 6};
        int[] expectedArr = {
    
    1, 2, 3, 5, 6, 8};
        Shell.shellSort(arr);
        System.out.println("arr = " + Arrays.toString(arr));
        Assertions.assertArrayEquals(expectedArr, arr);
    }
}

No código acima, a função shellSort recebe uma matriz de inteiros como entrada e a classifica usando o algoritmo de classificação Shell. O loop externo usa uma variável de intervalo gap com um valor inicial de metade do comprimento da matriz e divide o gap por 2 a cada vez através do loop até que o gap seja 1. O loop interno começa no elemento gapth, compara o elemento a ser inserido com os elementos da parte classificada e, se o elemento a ser inserido for menor que o elemento da parte classificada, move os elementos da parte classificada para a direita por posições de lacuna para abrir espaço para o elemento a ser inserido. Após o término do loop interno, inserimos o elemento a ser inserido na posição correta. Após cada iteração do loop externo, podemos garantir que os primeiros elementos de intervalo da matriz sejam classificados.

A classificação de Hill tem uma complexidade de tempo de O(n^2), mas na prática ela funciona muito melhor do que a classificação por inserção, especialmente em listas grandes. O desempenho do Hill sort depende da escolha da sequência do espaçador, mas ainda não existe uma sequência ideal do espaçador.

5. Mesclar classificação

Merge sort é um algoritmo de classificação do tipo dividir e conquistar. Sua ideia básica é dividir a matriz a ser classificada em várias subsequências, cada subsequência é ordenada e, em seguida, mesclar as subsequências em uma matriz ordenada.

import org.junit.jupiter.api.Assertions;
import java.util.Arrays;

public class Merge {
    
    
    public static void mergeSort(int[] arr, int left, int right) {
    
    
        if (left < right) {
    
    
            int mid = (left + right) / 2;
            mergeSort(arr, left, mid);
            mergeSort(arr, mid + 1, right);
            merge(arr, left, mid, right);
        }
    }

    public static void merge(int[] arr, int left, int mid, int right) {
    
    
        // 子数组 L 的大小
        int n1 = mid - left + 1;
        // 右子数组 R 的大小
        int n2 = right - mid;
        // 创建两个临时数组 L 和 R ,分别用来存储左子数组和右子数组的元素
        int[] L = new int[n1];
        int[] R = new int[n2];
        // 使用 for 循环将原始数组 arr 中的元素复制到临时数组 L 和 R 中,分别从 left 和 mid + 1 开始
        for (int i = 0; i < n1; i++) {
    
    
            L[i] = arr[left + i];
        }
        for (int j = 0; j < n2; j++) {
    
    
            R[j] = arr[mid + 1 + j];
        }
        // 初始化三个变量 i、j和k,分别指向数组 L 、R 和原始数组 arr 的起始位置
        int i = 0, j = 0, k = left;
        // 使用 while 循环,比较 L 和 R 的元素,并将较小的元素放回原始数组 arr 中
        while (i < n1 && j < n2) {
    
    
            if (L[i] <= R[j]) {
    
    
                arr[k] = L[i];
                i++;
            } else {
    
    
                arr[k] = R[j];
                j++;
            }
            k++;
        }
        // 当 L 或 R 中的元素用完时,将剩余的元素依次放回原始数组 arr 中
        while (i < n1) {
    
    
            arr[k] = L[i];
            i++;
            k++;
        }
        while (j < n2) {
    
    
            arr[k] = R[j];
            j++;
            k++;
        }
        // merge 方法执行完毕后,两个子数组范围内的元素已经按照从小到大的顺序合并到了原始数组 arr 中
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 8, 3, 1, 6};
        int[] expectedArr = {
    
    1, 2, 3, 5, 6, 8};
        Merge.mergeSort(arr, 0, arr.length - 1);
        System.out.println("arr = " + Arrays.toString(arr));
        Assertions.assertArrayEquals(expectedArr, arr);
    }
}

No código acima, a função mergeSort aceita um array inteiro, um índice esquerdo e um índice direito como entrada e usa o algoritmo de classificação por mesclagem para classificar os elementos do array dentro do intervalo especificado. Essa função usa recursão para dividir o array em dois sub-arrays, depois os classifica e finalmente os mescla em um array classificado. A função de mesclagem é usada para mesclar dois arrays classificados em um array classificado. Ele cria dois arrays temporários L e R, armazena os elementos do sub-array esquerdo em L e do sub-array direito em R, então os mescla em um array classificado e os armazena no array original.

A complexidade de tempo do merge sort é O(nlogn), e seu desempenho é muito melhor do que o bubble sort e o insert sort, especialmente em listas grandes.

6. Classificação rápida

A classificação rápida é um algoritmo de classificação com uma ideia de dividir e conquistar. Sua ideia básica é separar os registros a serem classificados em duas partes independentes por meio da classificação de uma passagem. As palavras-chave de uma parte dos registros são menores que as palavras-chave da outra parte dos registros e, em seguida, continuam a classificar as duas partes dos registros, respectivamente, para atingir o objetivo de ordenar a sequência inteira.

import org.junit.jupiter.api.Assertions;
import java.util.Arrays;

public class Quick {
    
    
    // 接收一个数组 arr,一个低索引 low ,和一个高索引 high 作为参数
    public static void quickSort(int[] arr, int low, int high) {
    
    
        // 检查 low 是否小于 high。如果不是,则意味着数组只有一个元素或为空,因此不需要排序
        if (low < high) {
    
    
            int pivot = partition(arr, low, high);
            quickSort(arr, low, pivot - 1);
            quickSort(arr, pivot + 1, high);
        }
    }

    private static int partition(int[] arr, int low, int high) {
    
    
        // 将最后一个元素作为枢轴元素( arr[high] )
        int pivot = arr[high];
        // 将 i 初始化为 low - 1,用于跟踪较小元素的索引
        int i = low - 1;
        for (int j = low; j < high; j++) {
    
    
            if (arr[j] < pivot) {
    
    
                // 如果当前元素 arr[j] 小于枢轴元素,则增加 i 并交换 arr[i] 和 arr[j]
                // 较小元素索引+1
                i++;
                // 将当前元素 arr[j] 放在较小元素索引位置
                swap(arr, i, j);
            }
            // 其他情况,则较小元素索引没有增加,说明当前元素应该放在右边
        }
        // 将枢轴元素( arr[high] )与索引 i + 1 处的元素交换。
        // 确保枢轴元素左边是较小元素,右边是较大元素
        swap(arr, i + 1, high);
        // 将 i + 1 作为枢轴索引返回
        return i + 1;
    }

    private static void swap(int[] arr, int i, int j) {
    
    
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 8, 6, 1, 3};
        int[] expectedArr = {
    
    1, 2, 3, 5, 6, 8};
        Quick.quickSort(arr, 0, arr.length - 1);
        System.out.println("arr = " + Arrays.toString(arr));
        Assertions.assertArrayEquals(expectedArr, arr);
    }
}

No código acima, a função quickSort recebe uma matriz inteira, um índice baixo e um índice alto como entrada e usa o algoritmo de classificação rápida para classificar os elementos da matriz dentro do intervalo especificado. Essa função usa recursão para dividir o array em dois sub-arrays, depois os classifica e finalmente os mescla em um array classificado. A função de partição é usada para dividir um array em dois subarrays. Ele seleciona o último elemento da matriz como o elemento pivô, coloca os elementos menores que o elemento pivô à esquerda e os elementos maiores que o elemento pivô à direita e retorna o índice do elemento pivô. A função swap é usada para trocar dois elementos em um array.

A complexidade de tempo do quicksort é O(nlogn), e seu desempenho é muito melhor do que o bubble sort e o insert sort, especialmente em listas grandes.

7. Classificação da pilha

A classificação de pilha é um algoritmo de classificação por seleção de árvore. Sua ideia básica é construir a matriz a ser classificada em uma grande pilha raiz (ou pequena pilha raiz), depois trocar a posição do elemento superior e inferior da pilha e, em seguida, reconstruir os elementos restantes em uma pilha e repetir a operação de troca e reconstrução da pilha até que toda a matriz esteja em ordem.

Heap sort é um algoritmo de classificação baseado na estrutura de dados heap e sua complexidade de tempo é O(nlogn).

conceito de pilha

O conjunto K = {k0, k1, k2, ..., kn-1} armazena todos os seus elementos em uma matriz unidimensional na ordem de uma árvore binária completa e satisfaz: Ki <= K2i+1 (nó esquerdo) e Ki<=K2i+2 (nó direito), então é chamado de pilha pequena (ou pilha grande). O heap com o maior nó raiz é chamado de heap maior ou heap raiz grande, e o heap com o menor nó raiz é chamado de heap menor ou heap raiz pequeno. Árvore binária completa (exceto para a última camada, os nós superiores não estão vazios e os nós da última camada são organizados da esquerda para a direita)

A natureza da pilha

1. O valor de um nó na pilha é sempre não maior ou menor que o valor de seu nó pai,
2. A pilha é sempre uma árvore binária completa.

public class Heap {
    
    

    public static void heapSort(int[] arr) {
    
    
        int n = arr.length;
        // 构建大根堆
        // 这段代码是构建大根堆的过程,它的循环次数为n/2-1次,是因为在完全二叉树中,叶子节点不需要进行堆化操作,
        // 所以只需要对非叶子节点进行堆化,而非叶子节点的数量为n/2-1个。因此,只需要循环n/2-1次即可完成大根堆的构建。
        // 非叶子节点在一维数组中就是前面 n/2-1
        for (int i = n / 2 - 1; i >= 0; i--) {
    
    
            heapify(arr, n, i);
        }
        // 依次取出堆顶元素,并将余下元素继续堆化,得到有序序列
        for (int i = n - 1; i >= 0; i--) {
    
    
            swap(arr, 0, i);
            heapify(arr, i, 0);
        }
    }

    private static void heapify(int[] arr, int heapSize, int i) {
    
    
        int largest = i; // 初始化最大值为根节点
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        // 找到左右子节点中的最大值
        if (left < heapSize && arr[left] > arr[largest]) {
    
    
            largest = left;
        }
        if (right < heapSize && arr[right] > arr[largest]) {
    
    
            largest = right;
        }
        // 如果最大值不是根节点,则交换根节点与最大值节点,并递归地对最大值节点进行堆化
        if (largest != i) {
    
    
            swap(arr, i, largest);
            heapify(arr, heapSize, largest);
        }
    }

    private static void swap(int[] arr, int i, int j) {
    
    
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 8, 3, 12, 35, 57, 1, 6};
        int[] expectedArr = {
    
    1, 2, 3, 5, 6, 8, 12, 35, 57};
        Heap.heapSort(arr);
        System.out.println("arr = " + Arrays.toString(arr));
        Assertions.assertArrayEquals(expectedArr, arr);
    }
}

No código acima, a função heapSort recebe uma matriz de inteiros como entrada e classifica a matriz usando o algoritmo heapsort. Essa função primeiro cria um grande heap raiz e, em seguida, retira os elementos superiores do heap para obter uma sequência ordenada. A função heapify é usada para empilhar um nó. São necessários três parâmetros: o array a ser empilhado, o tamanho do array e o índice do nó a ser empilhado. Esta função primeiro encontra o valor máximo entre os nós filho esquerdo e direito. Se o valor máximo não for o nó raiz, então troque o nó raiz e o nó de valor máximo e empilhe recursivamente o nó de valor máximo. A função swap é usada para trocar dois elementos em um array.

8. Ordenação por contagem

A classificação por contagem é um algoritmo de classificação não comparativo. Sua ideia básica é contar o número de ocorrências de cada elemento na matriz e, em seguida, colocar os elementos em uma matriz ordenada de acordo com o número de ocorrências do elemento.

A complexidade de tempo da ordenação por contagem é O(n+k), onde k é o número máximo de elementos a serem ordenados.

import org.junit.jupiter.api.Assertions;
import java.util.Arrays;

public class Counting {
    
    
    public static void countingSort(int[] arr) {
    
    
        int n = arr.length;
        // 取出数组中最大值
        int max = getMax(arr);
        int[] count = new int[max + 1];
        // 统计每个元素出现的次数
        for (int i = 0; i < n; i++) {
    
    
            count[arr[i]]++;
        }
        // 计算每个元素在有序序列中的位置
        for (int i = 1; i <= max; i++) {
    
    
            // 因为count包含了每个数据出现的次数,所以从小到大,逐个往前加得到就是原数组中每个元素在有序序列中应有的位置
            count[i] += count[i - 1];
        }
        // 输出有序序列
        int[] sortedArr = new int[n];
        for (int i = n - 1; i >= 0; i--) {
    
    
            sortedArr[count[arr[i]] - 1] = arr[i];
            count[arr[i]]--;
        }
        // 将有序序列复制回原数组
        System.arraycopy(sortedArr, 0, arr, 0, n);
    }

    private static int getMax(int[] arr) {
    
    
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
    
    
            if (arr[i] > max) {
    
    
                max = arr[i];
            }
        }
        return max;
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 8, 3, 1, 6, 12};
        int[] expectedArr = {
    
    1, 2, 3, 5, 6, 8, 12};
        Counting.countingSort(arr);
        System.out.println("arr = " + Arrays.toString(arr));
        Assertions.assertArrayEquals(expectedArr, arr);
    }
}

9. Classificação de balde

A classificação de balde é um algoritmo de classificação não comparativo. Sua ideia básica é dividir o array a ser classificado em um número limitado de baldes, depois classificar cada balde e, finalmente, retirar os elementos de todos os baldes para formar um array ordenado.

A complexidade de tempo da classificação de bucket é O(n), onde n é o número de elementos a serem classificados.

import org.junit.jupiter.api.Assertions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Bucket {
    
    
    /**
     * 桶排序
     * @param arr 待排序数组
     * @param bucketSize 桶大小,数据不宜过大,桶越大,后续对桶内数据排序越耗时
     */
    public static void bucketSort(int[] arr, int bucketSize) {
    
    
        if (arr.length == 0) {
    
    
            return;
        }
        // 循环数组,先找到最小值和最大值
        int minValue = arr[0];
        int maxValue = arr[0];
        for (int i = 1; i < arr.length; i++) {
    
    
            if (arr[i] < minValue) {
    
    
                minValue = arr[i];
            } else if (arr[i] > maxValue) {
    
    
                maxValue = arr[i];
            }
        }
        // 根据桶的大小,计算桶个数,并初始化桶
        int bucketCount = (maxValue - minValue) / bucketSize + 1;
        List<List<Integer>> buckets = new ArrayList<>(bucketCount);
        for (int i = 0; i < bucketCount; i++) {
    
    
            buckets.add(new ArrayList<>());
        }
        for (int i = 0; i < arr.length; i++) {
    
    
            int bucketIndex = (arr[i] - minValue) / bucketSize;
            buckets.get(bucketIndex).add(arr[i]);
        }
        int currentIndex = 0;
        for (int i = 0; i < bucketCount; i++) {
    
    
            List<Integer> bucket = buckets.get(i);
            // 对桶内数据进行排序
            Collections.sort(bucket);
            // 将数据逐个从桶内取出,并存入数组
            for (int j = 0; j < bucket.size(); j++) {
    
    
                arr[currentIndex++] = bucket.get(j);
            }
        }
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 8, 3, 12, 35, 57, 1, 6};
        int[] expectedArr = {
    
    1, 2, 3, 5, 6, 8, 12, 35, 57};
        Bucket.bucketSort(arr, 20);
        System.out.println("arr = " + Arrays.toString(arr));
        Assertions.assertArrayEquals(expectedArr, arr);
    }
}

No código acima, a função bucketSort usa uma matriz de inteiros e o tamanho do balde como entrada e classifica a matriz usando o algoritmo de classificação de balde. A função primeiro encontra os valores mínimo e máximo na matriz de entrada e conta o número de baldes. Em seguida, a função cria uma lista de baldes cujo tamanho é o número de baldes para armazenar os elementos em cada balde. Em seguida, a função itera por meio da matriz de entrada, colocando cada elemento no balde correspondente. Em seguida, a função classifica os elementos em cada balde e mescla os elementos classificados para obter uma sequência ordenada.

10. Classificação Radix

A classificação Radix é um algoritmo de classificação não comparativo. Sua ideia básica é dividir a matriz a ser classificada de acordo com o número de dígitos (unidades, dezenas e centenas) e, em seguida, classificar os números em cada dígito sucessivamente para finalmente obter uma matriz ordenada.

A complexidade de tempo da classificação radix é O(d(n+k)), onde d é o número de dígitos do maior elemento, n é o número de elementos a serem classificados e k é o número de baldes.

import org.junit.jupiter.api.Assertions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Radix {
    
    
    public static void radixSort(int[] arr) {
    
    
        if (arr.length == 0) {
    
    
            return;
        }
        int maxNum = arr[0];
        for (int i = 1; i < arr.length; i++) {
    
    
            if (arr[i] > maxNum) {
    
    
                maxNum = arr[i];
            }
        }
        int maxDigit = 0;
        while (maxNum != 0) {
    
    
            maxNum /= 10;
            maxDigit++;
        }
        List<List<Integer>> buckets = new ArrayList<>(10);
        for (int i = 0; i < 10; i++) {
    
    
            buckets.add(new ArrayList<>());
        }
        int mod = 10; // 初始10,用于数据个位数取模
        int div = 1; // 桶序号除数
        // 按位数循环数组,如果数据中有十位数的数据,循环2次,百位数循环3次
        for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) {
    
    
            // 循环数组,将数据分别存入桶中
            for (int j = 0; j < arr.length; j++) {
    
    
                // 计算当前位数的桶序号
                int bucketIndex = (arr[j] % mod) / div;
                buckets.get(bucketIndex).add(arr[j]);
            }
            // 循环桶列表,将当前位数已排序的数据放入数组中
            int currentIndex = 0;
            for (int j = 0; j < 10; j++) {
    
    
                List<Integer> bucket = buckets.get(j);
                for (int k = 0; k < bucket.size(); k++) {
    
    
                    arr[currentIndex++] = bucket.get(k);
                }
                bucket.clear();
            }
        }
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 8, 3, 12, 35, 57, 1, 6};
        int[] expectedArr = {
    
    1, 2, 3, 5, 6, 8, 12, 35, 57};
        Radix.radixSort(arr);
        System.out.println("arr = " + Arrays.toString(arr));
        Assertions.assertArrayEquals(expectedArr, arr);
    }
}

No código acima, a função radixSort recebe uma matriz de inteiros como entrada e classifica a matriz usando o algoritmo de classificação radix. A função primeiro localiza o valor máximo na matriz de entrada e calcula o número de dígitos no valor máximo. A função então cria uma lista de baldes de tamanho 10 para armazenar os elementos em cada balde. Em seguida, a função itera cada bit da matriz de entrada por vez, colocando cada elemento em seu balde correspondente. Em seguida, a função combina os elementos em cada balde para obter uma sequência ordenada.

Acho que você gosta

Origin blog.csdn.net/wlddhj/article/details/131482951
Recomendado
Clasificación