Algoritmo de clasificación Java detallado comúnmente utilizado (10 tipos)

Los algoritmos de clasificación comúnmente utilizados en Java son los siguientes:

  1. Ordenamiento de burbuja
  2. Clasificación de selección
  3. Tipo de inserción
  4. Clasificación de concha (clasificación de concha)
  5. Ordenar por fusión
  6. Ordenación rápida (Quick Sort)
  7. Ordenar montón
  8. Clasificación de conteo
  9. Clasificación de cubo
  10. Ordenación por Radix (Ordenación por Radix)

Estos algoritmos de clasificación tienen sus propias ventajas y desventajas, y se debe seleccionar el algoritmo apropiado según la situación específica.

1. Clasificación de burbujas

Bubble sort es un algoritmo de clasificación simple que atraviesa repetidamente la matriz que se va a clasificar, comparando dos elementos a la vez e intercambiando posiciones si están en el orden incorrecto. Este proceso continúa hacia el final de la secuencia hasta que se ordena toda la secuencia.

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);
    }
}

En el código anterior, la función bubbleSort toma una matriz de enteros como entrada y los ordena usando el algoritmo de clasificación de burbujas. El ciclo externo se ejecuta n - 1 veces, donde n es la longitud de la matriz, y el ciclo interno se ejecuta n - i - 1 veces, donde i es el número de iteración actual del ciclo externo. Esto se debe a que, después de cada iteración del ciclo externo, el elemento más grande definitivamente se encuentra al final de la matriz, por lo que no es necesario volver a compararlo.

En el ciclo interno comparamos elementos adyacentes y los intercambiamos si no están en el orden correcto. De esta manera, el elemento más grande "burbujea" hasta el final de la matriz. Después de cada paso por la matriz, el elemento más grande está en su posición final, por lo que podemos reducir el tamaño del ciclo interno en 1.

La complejidad temporal de la ordenación de burbujas es O(n^2), lo que la hace ineficiente para listas grandes y aplicaciones prácticas. Sin embargo, debido a su simplicidad, es un buen algoritmo para enseñar clasificación a principiantes.

2. Clasificación de selección

La ordenación por selección es un algoritmo de ordenación simple. Su idea básica es seleccionar el elemento más pequeño (o más grande) de los elementos a ordenar cada vez, y almacenarlo al comienzo de la secuencia hasta que se agoten todos los elementos a ordenar.

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);
    }
}

En el código anterior, la función SelectionSort toma una matriz de enteros como entrada y la ordena usando el algoritmo de ordenación por selección. El ciclo externo se ejecuta n - 1 veces, donde n es la longitud de la matriz. En el ciclo interno, encontramos el elemento más pequeño en la parte no ordenada y almacenamos su índice en la variable minIndex. Luego intercambiamos el elemento más pequeño con el final de la parte ordenada. Después de cada iteración del ciclo externo, la longitud de la parte clasificada aumenta en 1 y la longitud de la parte no clasificada disminuye en 1.

La complejidad temporal del ordenamiento por selección es O(n^2), lo que lo hace ineficiente para listas grandes y aplicaciones prácticas. Sin embargo, debido a su simplicidad, es un buen algoritmo para enseñar clasificación a principiantes.

3. Clasificación por inserción

La clasificación por inserción es un algoritmo de clasificación simple cuya idea básica es insertar un registro en una lista ordenada ya ordenada para obtener una nueva lista ordenada con el número de registros aumentado en 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);
    }
}

En el código anterior, la función de ordenación por inserción toma una matriz de enteros como entrada y la ordena mediante el algoritmo de ordenación por inserción. El bucle exterior comienza con el segundo elemento, ya que consideramos el primer elemento como la parte ordenada. En el bucle interno, comparamos el elemento que se va a insertar con el elemento de la parte ordenada, y si el elemento que se va a insertar es más pequeño que el elemento de la parte ordenada, desplazamos el elemento de la parte ordenada un bit a la derecha para dejar espacio para el elemento que se va a insertar. Después de que finaliza el bucle interno, insertamos el elemento que se insertará en la posición correcta. Después de cada iteración del ciclo externo, podemos asegurarnos de que los primeros elementos i hayan sido ordenados.

La ordenación por inserción tiene una complejidad de tiempo de O(n^2), lo que la hace ineficiente para listas grandes y aplicaciones prácticas. Sin embargo, la ordenación por inserción es muy simple de implementar y funciona muy bien en listas pequeñas.

4. Clasificación de conchas

Hill sorting es un algoritmo de clasificación por inserción mejorado. Su idea básica es agrupar la matriz que se va a clasificar de acuerdo con un cierto intervalo, clasificar cada grupo usando el algoritmo de clasificación por inserción, luego reducir el intervalo y luego clasificar la agrupación hasta que el intervalo sea 1.

El método de reducción gradual del tamaño del intervalo ayuda a mejorar la eficiencia del proceso de clasificación, lo que puede reducir el número de comparaciones e intercambios. Esta es una característica clave del algoritmo de clasificación Hill.

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);
    }
}

En el código anterior, la función shellSort toma una matriz de enteros como entrada y la ordena usando el algoritmo de ordenación de Shell. El ciclo externo usa una brecha variable de intervalo con un valor inicial de la mitad de la longitud de la matriz, y divide la brecha por 2 cada vez que pasa por el ciclo hasta que la brecha es 1. El bucle interno comienza en el elemento de espacio, compara el elemento que se va a insertar con los elementos de la parte ordenada y, si el elemento que se va a insertar es más pequeño que el elemento de la parte ordenada, mueve los elementos de la parte ordenada hacia la derecha en posiciones de espacio para dejar espacio para el elemento que se va a insertar. Después de que finaliza el bucle interno, insertamos el elemento que se insertará en la posición correcta. Después de cada iteración del ciclo externo, podemos asegurarnos de que se ordenen los primeros elementos de espacio de la matriz.

Hill sort tiene una complejidad de tiempo de O(n^2), pero en la práctica funciona mucho mejor que la ordenación por inserción, especialmente en listas grandes. El rendimiento de Hill sort depende de la elección de la secuencia espaciadora, pero aún no existe una secuencia espaciadora óptima.

5. Clasificación por fusión

Merge sort es un algoritmo de clasificación divide y vencerás. Su idea básica es dividir la matriz que se va a clasificar en varias subsecuencias, cada subsecuencia se ordena y luego fusionar las subsecuencias en una 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);
    }
}

En el código anterior, la función mergeSort acepta una matriz de enteros, un índice izquierdo y un índice derecho como entrada y utiliza el algoritmo de ordenación por combinación para ordenar los elementos de la matriz dentro del rango especificado. Esta función usa la recursividad para dividir la matriz en dos sub-matrices, luego las ordena y finalmente las fusiona en una matriz ordenada. La función de combinación se utiliza para combinar dos matrices ordenadas en una matriz ordenada. Crea dos arreglos temporales L y R, almacena los elementos del subarreglo izquierdo en L y el subarreglo derecho en R, luego los fusiona en un arreglo ordenado y lo almacena en el arreglo original.

La complejidad temporal de la ordenación por fusión es O(nlogn) y su rendimiento es mucho mejor que la ordenación por burbujas y la ordenación por inserción, especialmente en listas grandes.

6. Clasificación rápida

La clasificación rápida es un algoritmo de clasificación con una idea de divide y vencerás. Su idea básica es separar los registros que se clasificarán en dos partes independientes a través de la clasificación de un solo paso. Las palabras clave de una parte de los registros son más pequeñas que las palabras clave de la otra parte de los registros, y luego continúan clasificando las dos partes de los registros respectivamente, para lograr el propósito de ordenar la secuencia completa.

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);
    }
}

En el código anterior, la función quickSort toma una matriz de enteros, un índice bajo y un índice alto como entrada y utiliza el algoritmo de ordenación rápida para ordenar los elementos de la matriz dentro del rango especificado. Esta función usa la recursividad para dividir la matriz en dos sub-matrices, luego las ordena y finalmente las fusiona en una matriz ordenada. La función de partición se utiliza para dividir una matriz en dos subarreglos. Selecciona el último elemento de la matriz como elemento pivote, luego coloca los elementos más pequeños que el elemento pivote a la izquierda y los elementos más grandes que el elemento pivote a la derecha, y devuelve el índice del elemento pivote. La función de intercambio se utiliza para intercambiar dos elementos en una matriz.

La complejidad temporal de la ordenación rápida es O(nlogn) y su rendimiento es mucho mejor que la ordenación por burbujas y la ordenación por inserción, especialmente en listas grandes.

7. Clasificación en montón

La clasificación de montón es un algoritmo de clasificación de selección de árbol. Su idea básica es construir la matriz que se clasificará en un montón de raíz grande (o pequeño montón de raíz), luego intercambiar la posición del elemento superior y el elemento inferior del montón, y luego reconstruir los elementos restantes en un montón, y repetir la operación de intercambiar y reconstruir el montón hasta que toda la matriz esté en orden.

Heap sort es un algoritmo de clasificación basado en la estructura de datos de montón, y su complejidad de tiempo es O (nlogn).

concepto de montón

El conjunto K = {k0, k1, k2, ..., kn-1} almacena todos sus elementos en una matriz unidimensional en el orden de un árbol binario completo y satisface: Ki <= K2i+1 (nodo izquierdo) y Ki<=K2i+2 (nodo derecho), entonces se le llama montón pequeño (o montón grande). El montón con el nodo raíz más grande se denomina montón más grande o montón raíz grande, y el montón con el nodo raíz más pequeño se denomina montón más pequeño o montón raíz pequeño. Árbol binario completo (a excepción de la última capa, los nodos superiores no están vacíos y los nodos de la última capa están dispuestos de izquierda a derecha)

La naturaleza del montón.

1. El valor de un nodo en el montón siempre no es mayor ni menor que el valor de su nodo principal
2. El montón es siempre un árbol binario completo.

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);
    }
}

En el código anterior, la función heapSort toma una matriz de enteros como entrada y ordena la matriz utilizando el algoritmo heapsort. Esta función primero crea un montón raíz grande y luego saca los elementos superiores del montón para obtener una secuencia ordenada. La función heapify se utiliza para acumular un nodo. Toma tres parámetros: la matriz que se acumulará, el tamaño de la matriz y el índice del nodo que se acumulará. Esta función primero encuentra el valor máximo entre los nodos secundarios izquierdo y derecho. Si el valor máximo no es el nodo raíz, entonces intercambie el nodo raíz y el nodo de valor máximo, y acumule recursivamente el nodo de valor máximo. La función de intercambio se utiliza para intercambiar dos elementos en una matriz.

8. Ordenar por conteo

La ordenación por conteo es un algoritmo de ordenación no comparativa. Su idea básica es contar el número de ocurrencias de cada elemento en la matriz y luego colocar los elementos en una matriz ordenada a su vez de acuerdo con la cantidad de ocurrencias del elemento.

La complejidad temporal de la ordenación por conteo es O(n+k), donde k es el número máximo de elementos a ordenar.

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. Clasificación de cubeta

La clasificación de cubetas es un algoritmo de clasificación no comparativa. Su idea básica es dividir la matriz que se va a clasificar en un número limitado de cubetas, luego clasificar cada cubeta y, finalmente, sacar los elementos de todas las cubetas para formar una matriz ordenada.

La complejidad temporal de la clasificación de cubetas es O(n), donde n es el número de elementos que se clasificarán.

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);
    }
}

En el código anterior, la función bucketSort toma una matriz de enteros y el tamaño de la cubeta como entrada y ordena la matriz utilizando el algoritmo de clasificación de cubetas. La función primero encuentra los valores mínimo y máximo en la matriz de entrada y cuenta la cantidad de cubos. Luego, la función crea una lista de cubos cuyo tamaño es el número de cubos para almacenar los elementos en cada cubo. A continuación, la función itera a través de la matriz de entrada, colocando cada elemento en el depósito correspondiente. Luego, la función ordena los elementos en cada cubo y fusiona los elementos ordenados para obtener una secuencia ordenada.

10. Clasificación de Radix

Radix sorting es un algoritmo de clasificación no comparativo, su idea básica es dividir la matriz a clasificar según el número de dígitos (unidades, decenas y centenas) y luego ordenar los números en cada dígito para obtener finalmente una matriz ordenada.

La complejidad temporal de la clasificación de radix es O(d(n+k)), donde d es la cantidad de dígitos del elemento más grande, n es la cantidad de elementos que se clasificarán y k es la cantidad de cubos.

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);
    }
}

En el código anterior, la función radixSort toma una matriz de enteros como entrada y ordena la matriz usando el algoritmo de clasificación radix. La función primero encuentra el valor máximo en la matriz de entrada y calcula el número de dígitos en el valor máximo. Luego, la función crea una lista de cubos de tamaño 10 para almacenar los elementos en cada cubo. A continuación, la función itera a través de cada bit de la matriz de entrada, colocando cada elemento en su depósito correspondiente. Luego, la función combina los elementos en cada cubo para obtener una secuencia ordenada.

Supongo que te gusta

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