Ocho algoritmos de clasificación: clasificación de colinas (entendimiento de obsequios)

Tabla de contenido

clasificación de colinas

concepto

idea de algoritmo

animación

el código se muestra a continuación

Análisis de Complejidad

prueba de complejidad temporal

resultado de la operación

 código completo

 No es fácil de crear, si este blog es útil para usted, recuerde dejar un mensaje + me gusta.


clasificación de colinas

concepto

Hill sort es un tipo de ordenación por inserción, que es una optimización de la ordenación por inserción directa. Su característica radica en la agrupación y clasificación.

idea de algoritmo

Hill sorting lleva el nombre de su diseñador Hill, quien analizó la eficiencia de la clasificación por inserción y llegó a las siguientes conclusiones:

        1. En el peor de los casos, cuando la secuencia a ordenar está en orden inverso, toma O(n^2) tiempo
        2. En el mejor de los casos, cuando la secuencia a ordenar está en orden, toma O(n) tiempo


Así que Hill pensó: si la secuencia que se va a ordenar se puede preordenar primero, de modo que la secuencia que se va a ordenar esté cerca del orden, y luego se realiza una ordenación por inserción en la secuencia. Por lo tanto, la complejidad de tiempo de la clasificación por inserción directa es O(n) en este momento , por lo que solo es necesario controlar la complejidad de tiempo de la etapa de clasificación previa para que sea menor que O(n^2) , luego la complejidad de tiempo general es más bajo que el de la clasificación por inserción.

Entonces, ¿cómo se debe hacer la clasificación previa específica para que la complejidad del tiempo pueda cumplir con los requisitos?

        1. Primero, seleccione un espacio entero menor que n (generalmente, n/2 se usa como espacio) como el primer incremento, y luego agrupe todos los elementos cuya distancia sea un espacio en un grupo, y realice una ordenación por inserción en cada grupo 2. Repita el
        paso 1 hasta que el espacio sea igual a 1 y detenerse En este momento, toda la secuencia se divide en un grupo, se realiza una clasificación por inserción directa y se completa la clasificación.

Quizás se pregunte por qué la brecha es de grande a pequeña.

Porque cuanto mayor es la brecha, más rápido se mueven los datos y toma menos tiempo; cuanto más pequeña es la brecha, más lentos se mueven los datos y toma más tiempo. Haga que la brecha sea más grande en la etapa inicial, de modo que los datos puedan moverse rápidamente a la vecindad de su posición correspondiente, reduciendo la cantidad de veces de movimiento.

animación

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leeching, se recomienda guardar la imagen y cargarla directamente (img-3Is6Arbg-1668608929993) (Hillsort.assets/animation.gif)]

 

Tomemos un ejemplo:

 

Primero, el espacio es 5. En este momento, los elementos con una distancia de 5 se dividen en un grupo (un total de cinco grupos, cada uno con dos elementos), y luego cada grupo se inserta y ordena por separado.

 

El espacio se reduce a la mitad a 2. En este momento, los elementos con una distancia de 2 se dividen en un grupo (un total de dos grupos con cinco elementos en cada grupo), y luego cada grupo se inserta y ordena por separado.

 

El espacio se reduce a la mitad nuevamente a 1. En este momento, todos los elementos se dividen en un grupo, se insertan y ordenan, y la ordenación por inserción se completa.

 

En este ejemplo, los dos primeros viajes son la clasificación previa de la clasificación por colinas y el último viaje es la clasificación por inserción de la clasificación por colinas.
 

el código se muestra a continuación

public static void shellSort(int[] a){
        int gal = a.length;
        while(gal>1) {
            int j = 0;
            gal/=2;   //特别之处gal  分组排序 5 3 1.。。

            //核心
            for (int i = gal; i < a.length; i++) {
                j = i-gal;
                if(a[j] > a[i]) {
                    int tmp = a[j];
                    a[j] = a[i];
                    a[i] = tmp;
                }
            }

        }
    }

Análisis de Complejidad

La complejidad temporal de la clasificación de Hill no es fácil de calcular, porque hay muchas maneras de calcular el valor de la brecha, lo que hace que sea difícil de calcular. La siguiente es la explicación dada por los dos profesores en el libro.

 

 "Estructura de datos - Descripción con método orientado a objetos y C++ " --- Yin Renkun

     Complejidad de tiempo  n^1.3 -- n^1.5 No se sabe. Está relacionado con el número de huecos en cada grupo.
     Complejidad de espacio O(1)
     Estabilidad Inestable Cuando hay varios números idénticos, la posición relativa cambiará después de clasificarlos.

prueba de complejidad temporal

A continuación, intentemos probarlo con una gran cantidad de datos.

int[] a = new int[10_0000]; //prueba de 100.000 datos

1. La función orderArray se implementa para generar una secuencia ordenada básica, es decir, ordenada de menor a mayor.

public static void orderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = i;
        }
    }


2. La función notOrderArray genera una secuencia inversa, es decir, ordenada de mayor a menor.

public static void notOrderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = a.length-i;
        }
 
    }


3. La función randomArray genera una matriz desordenada aleatoria.

 public static void randomArray(int[] a) {
        Random random = new Random();
        for (int i = 0; i < a.length; i++) {
            a[i] = random.nextInt(10_0000);
        }
    }


4. La función testInsertSort prueba el valor de retorno de System.currentTimeMillis() en milisegundos .

 

 public static void testInsertSort(int[] a){
        int[] tmpArray = Arrays.copyOf(a,a.length);
        long startTime = System.currentTimeMillis();    //注意用long接收
        shellSort(tmpArray);
        long endTime = System.currentTimeMillis();  //返回单位是毫秒
        System.out.println("直接插入排序耗时:"+(endTime-startTime));
    }


5. Ejecución de la llamada a la función principal

public static void main(String[] args) {
 
 
        int[] a = new int[10_0000];
        //有序
        System.out.println("基本有序数列");
        orderArray(a);
        testInsertSort(a);
 
        //倒序
        System.out.println("逆序数列");
        notOrderArray(a);
        testInsertSort(a);
 
        //随机乱序
        System.out.println("无序数列");
        randomArray(a);
        testInsertSort(a);
 
    }

resultado de la operación

         

 Tanto la ordenación por colina como la ordenación por inserción directa son ordenaciones por inserción, y la ordenación por colina es una optimización de la ordenación por inserción directa. Compare los resultados de la prueba de la ordenación por inserción directa anterior .

            

 Se puede ver que la ordenación de Hill es, de hecho, mucho más rápida. Y lento y estable.

 código completo

import java.util.Random;

public class sort {

    public static void main(String[] args) {
       
        int[] a = new int[10_0000];
        //有序
        System.out.println("基本有序数列");
        orderArray(a);
        testInsertSort(a);

        //无序
        System.out.println("逆序数列");
        notOrderArray(a);
        testInsertSort(a);

        //乱序
        System.out.println("无序数列");
        randomArray(a);
        testInsertSort(a);


    }

    //希尔排序  是插入排序的优化
    //时间复杂度  n^1.3 -- n^1.5  说不准  与每次分组的个数有关
    //空间复杂度 O(1)
    //稳定性 不稳定 当有几个相同的数字时,排序后相对位置会改变
    public static void shellSort(int[] a){
        int gal = a.length;
        while(gal>1) {
            int j = 0;
            gal/=2;   //特别之处gal  分组排序 5 3 1.。。

            //核心
            for (int i = gal; i < a.length; i++) {
                j = i-gal;
                if(a[j] > a[i]) {
                    int tmp = a[j];
                    a[j] = a[i];
                    a[i] = tmp;
                }
            }

        }
    }

    //生成有序数组  从小到大排列
    public static void orderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = i;
        }
    }

    //n无序 其实就是从大到小排列
    public static void notOrderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = a.length-i;
        }

    }

    //乱序 随机生成序列
    public static void randomArray(int[] a) {
        Random random = new Random();
        for (int i = 0; i < a.length; i++) {
            a[i] = random.nextInt(10_0000);
        }
    }

    //大量数据测试
    public static void testInsertSort(int[] a){
        int[] tmpArray = Arrays.copyOf(a,a.length);
        long startTime = System.currentTimeMillis();    //注意用long接收
        shellSort(tmpArray);
        long endTime = System.currentTimeMillis();
        System.out.println("希尔排序耗时:"+(endTime-startTime));
    }

}

 No es fácil de crear, si este blog es útil para usted, recuerde dejar un mensaje + me gusta.

Supongo que te gusta

Origin blog.csdn.net/m0_73381672/article/details/132020520
Recomendado
Clasificación