Tipo de colina
A classificação de Hill é um algoritmo de classificação proposto por Hill (DonaldShell) em 1959. A classificação de shell também é uma classificação de inserção , que é uma classificação de inserção simples aprimorada após uma versão mais eficiente, também conhecida como classificação de redução incremental.
Ideia básica
A classificação Hill consiste em agrupar os registros por um determinado incremento do destino e usar o algoritmo de classificação por inserção direta para classificar cada grupo; à medida que o incremento diminui, cada grupo contém mais e mais palavras-chave. Quando o incremento diminui para 1, o arquivo inteiro é dividido em um grupo e o algoritmo termina
Explicação
Vejamos o diagrama dinâmico comum de classificação Hill
Muito rápido?
Venha em um ícone estático
Já muito próximo do ordenado, mesmo se você precisar mover para inserir, ele irá mover 1 a 2 etapas, podemos usar a classificação por inserção direta para classificar este grande grupo
Claro, quando inserimos uma sequência ordenada, como a inserimos?
Existem ** método de troca, método de movimento ** vamos escrever e testar separadamente
Por favor, ouça a pergunta :
10 pessoas de HKUST foram entrevistar a comunidade CSDN. A pontuação total é de 10 pontos. Agora, as pontuações dadas são 8,9,1,7,2,3,5,4,6,0. Use Hill Sort para classificá-las de pequeno a grande
Processo de derivação do método de troca
package com.wang.sort;
import java.util.Arrays;
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/24 17:11
* @Description TODO
* @pojectname 希尔排序算法
*/
public class ShellSort {
public static void main(String[] args) {
int[] arr = {
8,9,1,7,2,3,5,4,6,0};
ShellSort(arr);
}
//交换法逐步推导过程
public static void ShellSort(int[] arr){
int temp = 0;
//希尔排序的第一轮排序
//分组,我们例子是10个数据除以二就是5组
for (int i = 5; i <arr.length ; i++) {
//遍历各组中所有的元素,共有5组,每组2个元素
//步长是5 5-5=0 6-5=1 7-5=2
for (int j = i-5; j >=0 ; j-=5) {
//如果当前元素大于加上步长后的元素,说明需要交换
if (arr[j]>arr[j+5]){
//0>6 1>7 2>8 3>9 4>10
temp = arr[j];
arr[j] = arr[j+5];
arr[j+5] = temp;
}
}
}
System.out.println("希尔排序第一轮后"+ Arrays.toString(arr));
//第二轮
//在第一组的基础上,5组再除以2 分为2组,步长变为2
for (int i = 2; i <arr.length ; i++) {
//遍历各组中所有的元素,共有5组,每组2个元素
for (int j = i-2; j >=0 ; j-=2) {
//如果当前元素大于加上步长后的元素,说明需要交换
if (arr[j]>arr[j+2]){
//0>6 1>7 2>8 3>9 4>10
temp = arr[j];
arr[j] = arr[j+2];
arr[j+2] = temp;
}
}
}
System.out.println("第二轮希尔排序后的结果"+Arrays.toString(arr));
//第三轮
//在第二组的基础上,2组再除以2 分为1组,步长变为1
for (int i = 1; i <arr.length ; i++) {
//遍历各组中所有的元素,共有5组,每组2个元素
for (int j = i-1; j >=0 ; j-=1) {
//如果当前元素大于加上步长后的元素,说明需要交换
if (arr[j]>arr[j+1]){
//0>6 1>7 2>8 3>9 4>10
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println("第三轮希尔排序后的结果"+Arrays.toString(arr));
}
}
Método de troca Hill Sort
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/24 17:11
* @Description TODO
* @pojectname 希尔排序算法
*/
public class ShellSort {
public static void main(String[] args) {
int[] arr = {
8,9,1,7,2,3,5,4,6,0};
ShellSort(arr);
}
//交换法逐步推导过程
public static void ShellSort(int[] arr){
int temp = 0;
int count = 0;
for (int gap = arr.length/2; gap >0 ; gap/=2) {
for (int i = gap; i <arr.length ; i++) {
for (int j = i-gap; j >=0 ; j-=gap) {
if (arr[j]>arr[j+gap]){
temp = arr[j];
arr[j] = arr[j+gap];
arr[j+gap] = temp;
}
}
}
System.out.println("希尔排序"+(count++)+"轮"+Arrays.toString(arr));
}
}
}
O loop for externo controla em quantos grupos são divididos. Por coincidência, descobrimos que essa lacuna também é o tamanho do nosso passo, e o comprimento do passo também é controlado por ele. Isso é uma coincidência. Por exemplo, a primeira vez que dividimos em 5 grupos, isto é
for(int gap = 5;gap>0;gap=2){
for(int i=gap;i<arr.length;i++){
for(int j = i - gap;j>=0;j-=gap){
我们就拿第一个数据来举例;
8 和 3;
if(8>3){
//a[0]>a[5]
交换;然后j=j-gap=0-5跳出最内层循环
让i++变成6再进入最内层循环
也就是这次是a[j=1]和a[j+gap=6]比较 9>5交换
我们的j=j-gap=-4 跳出i变成2再进来依次类推
}
}
}
}
Baixa eficiência, temos o método de classificação Hill de inserção, que é mais eficiente
Classificação mais rápida para celular
Por que o método de troca do tipo Hill é tão lento?
Porque nossa troca temp = arr [j]; arr [j] = arr [j + gap]; arr [j + gap] = temp; é muito caro, nosso tipo de inserção direta é inserido diretamente nessa posição, sem necessidade de troca para frente e para trás, então a troca de classificação Fashir é lenta
Então, como o tipo Fasher móvel se sai?
Código
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/24 17:11
* @Description TODO
* @pojectname 希尔排序算法
*/
public class ShellSort {
public static void main(String[] args) {
int[] arr = {
8,9,1,7,2,3,5,4,6,0};
shellSort2(arr);
System.out.println(Arrays.toString(arr));
}
public static void shellSort2(int[] arr){
//增量gap,并逐步缩小增量
for (int gap = arr.length/2; gap >0 ; gap/=2) {
//从第gap个元素,逐个对其所在的组进行直接插入排序
for (int i = gap; i <arr.length ; i++) {
int j = i;//带插入的下标先保存起来
int temp = arr[j];
if (arr[j] < arr[j-gap]){
while (j - gap>=0 && temp< arr[j-gap]){
//继续找位置
//移动
arr[j] = arr[j-gap];
j-=gap;//向前移动
}
//退出循环时,找到位置
arr[j] = temp;
}
}
}
}
}
Para explicar em texto :
A maneira antiga é usar os dados como exemplo. Nosso loop de primeiro nível é usado para agrupar e formular o comprimento do nosso passo . Na primeira vez que entramos, há 5 grupos, cada grupo tem 2 dados e o comprimento do passo é 5.
No segundo loop , primeiro obtemos nossa posição inicial, 5, temp = arr [5] = 3, que é o sexto dado, e também é o segundo dado do primeiro grupo! ! Então, quando entramos no julgamento if , descobrimos que j-gap corresponde a outros dados no mesmo grupo que ele, que é 8. Os dois julgamentos, o resto é muito semelhante ao nosso tipo de inserção direta, a diferença é o lugar para onde nos mudamos , que costumava ser -1, mas agora se tornou -gap step size, o que significa que o mesmo grupo vê a troca de dados. Se você não entender, podemos depurar para interromper a função e seguir o programa.