Desmontaje y análisis del algoritmo de clasificación Hill

Prólogo : Después de leer muchas explicaciones en Internet, no parece muy intuitivo. Así que planeo usar una lengua vernácula para explicar claramente el algoritmo de Hill. Todo el mundo sabe que en realidad es una versión mejorada del ordenamiento por inserción. Todos sabemos que si hay más números ordenados localmente en un conjunto de datos, la ordenación por inserción más eficiente es. (Si no lo entiende, puede ir a comprender). Conociendo esta característica, nació el algoritmo Hill.

Primero, revisemos el orden de inserción

//比如有组数据:
int[] arr = {
    
    8, 6, 2, 3, 1, 5, 7, 4};

Resumen de texto: suponga que el primer elemento es el número más pequeño. Luego, tenemos que retroceder desde el índice = 1, tomar los siguientes números por turno y compararlos con los números anteriores para encontrar el número más pequeño. Es decir, cuando índice = 1, entonces arr [1] se compara con arr [0]. Cuando index = 2, compare arr [2] con arr [1] para obtener un valor mínimo y luego compare con arr [0]. Finalmente complete la clasificación de pequeño a grande.

Entonces el código es el siguiente

	//{8, 6, 2, 3, 1, 5, 7, 4}
    public void inseartSort(int[] arr) {
    
    
		//所以外层循环,我们跳过第一个元素 8,拿后面的数和前面的数比较
        for (int i = 1; i < arr.length; i++) {
    
    
			//1、这层的循环是拿后面的数和前面的【依次比较】得出最小数
            //2、下面内层循环不知道怎么写,我们可以先来拆分下逻辑
            //   (1)先看外层循环,index = 1,我们要拿arr[1]与arr[0]比较,较小的数字排在前面
            //   (2)继续看外层循环,index = 2,我们首先要拿arr[2]和arr[1]作比较,得出最小数后,继续和arr[0]做比较。
            // 	      相当于index--了。
			//	 (3)综上所述:外层循环的起始点,就是内层循环的起始点,其次index--才能依次和前面的数比较,做好排序。
            //        既然是index--,那么index要满足的条件是index > 0 。不然异常。所以代码如下
            for (int j = i; j > 0; j--) {
    
    
                if (arr[j] < arr[j - 1]) {
    
    
                    int temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }


Segundo, tipo Hill

Conoce el algoritmo de ordenación por inserción. Un conjunto de datos muy extenso. Cuantos más números ordenados localmente, más eficiente sea la ordenación por inserción y mejor será el rendimiento.
Algoritmo Hill: se mejora utilizando las características de este tipo de inserción. Tiene un concepto de brecha incremental aquí. No discutiremos la complejidad temporal que trae consigo la secuencia incremental por el momento.

Si sigue siendo ese conjunto de datos: {8, 6, 2, 3, 1, 5, 7, 4}. Suponga que el incremento aquí es gap = arr.length / 2. Es decir, 4, agrupará la matriz lógicamente en varias partes (también se puede considerar que el incremento es de varias partes), y luego insertará y ordenará los grupos lógicos a su vez, y la matriz seguirá siendo la misma matriz. Use gap / = 2 después de ordenar. Eso es 2. Continúe agrupando lógicamente, continúe insertando ordenar. De esta forma, la mayoría de los datos de la matriz original son datos ordenados. Finalmente, gap = 1, inserte ordenando la matriz donde la mayoría de los datos son datos ordenados. Entonces la velocidad es mucho más rápida, el rendimiento es conveniente y muy eficiente.

Puede ser muy general, consulte el análisis.


2.1, cuando brecha = 4

Cuando brecha = 4, entonces

  • conjunto de arr [0] y arr [4]
  • conjunto de arr [1] y arr [5]
  • conjunto de arr [2] y arr [6]
  • arr [3] y arr [7] un conjunto
//数据就对应如下
8  6  2  3  1  5  7  4
|  |  |  |  |  |  |  |
8--|--|--|--1  |  |  |  
   6--|--|-----5  |	 |
	  2--|--------7  |
		 3-----------4

Esta es una agrupación lógica,

  • Después de ordenar 8 y 1: 1 8;
  • Después de clasificar 5 y 6: 5 6;
  • Después de clasificar 2 y 7: 2 7;
  • Después de ordenar 3 y 4: 3 4.
8  6  2  3  1  5  7  4
|  |  |  |  |  |  |  |
1--|--|--|--8  |  |  |  
   5--|--|-----6  |	 |
	  2--|--------7  |
		 3-----------4

Mirando verticalmente, los resultados de la clasificación son: 1 5 2 3 8 6 7 4


2.2, cuando brecha = 2

Cuando el espacio sea 2, se separará por 2 para agrupar, por supuesto, se dividirá en 2 grupos.

1  5  2  3  8  6  7  4
|  |  |  |  |  |  |  |
1--|--2--|--8--|--7  |  
   |     |     |     |
   |     |     |     |
   5-----3-----6-----4

La agrupación cuando gap = 2 es

  • 1 2 8 7; después de clasificar, 1 2 7 8
  • 5 3 6 4; después de clasificar, 3 4 5 6

Entonces es

1  5  2  3  8  6  7  4
|  |  |  |  |  |  |  |
1--|--2--|--7--|--8  |  
   |     |     |     |
   |     |     |     |
   3-----4-----5-----6

Mirando verticalmente, los resultados de la clasificación son: 1 3 2 4 7 5 8 6

Finalmente, cuando gap = 1, es una ordenación de inserción normal. Algunas personas pueden decir que si lo hace en incrementos, el último conjunto de datos no está en orden para la mayoría de los números. Porque a los efectos de la explicación, elegí un tamaño de datos relativamente pequeño = 8. Si el tamaño> = 100000, será muy obvio.


Tres, la expresión java de la clasificación Hill

A través de la explicación anterior, sabemos. De hecho, la clasificación Hill tiene un concepto adicional de incremento, que prácticamente no ha cambiado.

En primer lugar, conocemos el cambio de la brecha incremental

//不难理解,gap最终变化是4,2,1
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
    
    }

A continuación, cuando ponemos gap = 1, es decir, el código para la ordenación por inserción normal se mueve directamente en


   for (int gap = arr.length / 2; gap > 0; gap /= 2) {
    
    
        for (int i = 1; i < arr.length; i++) {
    
    
            for (int j = i; j > 0; j--) {
    
    
                if (arr[j] < arr[j - 1]) {
    
    
                    int temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }
    
    
    
   //上面式子看不大出来,我们把它变一下如下
   //看看哪里时候把gap加上
   for (int gap = arr.length / 2; gap > 0; gap /= 2) {
    
    
        for (int i = 1; i < arr.length; i++) {
    
    
            for (int j = i; j >= 1; j-=1) {
    
     //主要是修改了j>0 改成了 j>=1。 j-- 改成了 j-=1
                if (arr[j] < arr[j - 1]) {
    
    
                    int temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }




//改完之后,我们把gap=1的情况改成gap。也就是把1改成gap变化如下
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
    
    
            for (int i = gap; i < arr.length; i++) {
    
    
                for (int j = i; j >= gap; j -= gap) {
    
    
                    if (arr[j] < arr[j - gap]) {
    
    
                        int temp = arr[j - gap];
                        arr[j - gap] = arr[j];
                        arr[j] = temp;
                    }
                }
            }
        }


Bueno, eso es todo para la clasificación de Hill. A continuación, lo imprimimos para verificar la lógica inicial:

Supongo que te gusta

Origin blog.csdn.net/leol_2/article/details/107982564
Recomendado
Clasificación