Estrutura e algoritmo de dados - Método de troca de classificação de Hill + método de movimentação

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

img

Muito rápido?

Venha em um ícone estático

Insira a descrição da imagem aqui

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){
    
    
            我们就拿第一个数据来举例;
           	83;
            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.

Acho que você gosta

Origin blog.csdn.net/qq_22155255/article/details/111657017
Recomendado
Clasificación