Data structure and algorithm--Hill sort-exchange method + move method

Hill sort

Hill sorting is a sorting algorithm proposed by Hill (DonaldShell) in 1959. Shell sort is also an insertion sort , which is a simple insertion sort through improved after a more efficient version, also referred to as incremental reduction sorting.

Basic idea

Hill sorting is to group the records by a certain increment of the target , and use the direct insertion sorting algorithm to sort each group; as the increment decreases, each group contains more and more keywords. When the increment decreases to 1, The entire file is divided into one group, and the algorithm terminates

Explanation

Let's look at the common dynamic diagram of Hill sorting

img

Too fast?

Come on a static icon

Insert picture description here

Already very close to orderly, even if you need to move to insert, it will move 1 to 2 steps, we can use the direct insertion sort to sort this large group

Of course, when we insert an ordered sequence, how do we insert it?

There are ** exchange method, movement method, ** let’s write down and test separately

Please listen to the question :

10 people from HKUST went to interview the CSDN community. The full score is 10 points. Now the scores given are 8,9,1,7,2,3,5,4,6,0. Please use Hill sorting to rank them from small to large

Derivation process of exchange method

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

Hill Sort Exchange Method

/**
 * @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));
        }
     }
}      

The outer for loop controls how many groups are divided into. It happens that we find that this gap is also our step length, and the step length is also controlled by it. This is a coincidence. For example, we divided into 5 groups for the first time.

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再进来依次类推
                    
            }
        }
    }
}

Low efficiency, we have Hill sorting of insertion method, which is more efficient

Mobile Fasher Sort

Why is the Hill sort of exchange method so slow?

Because our exchange temp = arr[j]; arr[j] = arr[j+gap]; arr[j+gap] = temp; is very expensive, our direct insertion sort is directly inserted into that position, no Need to exchange back and forth, so exchange Fashir sort is slow

So how does the mobile Fasher sort do?

Code

/**
 * @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;
                }
            }
        }
    }
}

To explain it in text :

The old way is to take data as an example. Our first-level loop is used to group and formulate our step length . The first time we enter, there are 5 groups, each group has 2 data, and the step length is 5.

In the second loop , we first get our starting position, 5, temp=arr[5]=3, which is the sixth data, and it is also the second data of the first group! ! Then when we enter the if judgment , we find that j-gap corresponds to another data in the same group, which is 8. The two judgments, the rest is very similar to our direct insertion sort, the difference is It lies in the place where we moved , which used to be -1, but now it has become -gap step size, which means that the same group sees data exchange. If you don’t understand, we can debug to interrupt the function and follow the program.

Guess you like

Origin blog.csdn.net/qq_22155255/article/details/111657017