【Java数据结构与算法】希尔排序

希尔排序

基本介绍

希尔排序是希尔(DonaldShell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序

插入排序文章:插入排序

希尔排序法基本思想:
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便停止。

希尔排序算法的过程

原始数组:8 9 1 7 2 3 5 4 6 0

初始增量 gap = length / 2 = 5,意味着整个数组被分为5组,[8,3] [9,5,] [1,4] [7,6] [2,0]

对这5组分班进行直接插入排序,结果如下,可以看到,像3,5,6这些小元素,都被调到了前面,然后缩小增量gap = 5 / 2 = 2,数组被分为 2 组 [3,1,0,9,7] [5,6,8,4,2]

进行一轮之后:3 5 1 6 0 8 9 4 7 2

对以上2组再分班进行直接插入排序,结果如下,可以看到,此时整个数组的有序成都更进一步,再缩小增量gap = 2 / 2 = 1,此时,整个数组为1组[0,2,1,4,3,5,7,6,9,8]

又进行一轮之后:0 2 1 4 3 5 7 6 9 8

经过上面的“宏观调控”,整个数组的有序化程度成果喜人。此时,仅仅需要对以上数列简单微调,无序大量移动操作即可完成整个数组的排序。

最终结果: 0 1 2 3 4 5 6 7 8 9

代码实现交换法(不推荐使用)

package sort;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ShellSort {
    public static void main(String[] args) {

        //int[] arr1 = {8,9,1,7,2,3,5,4,6,0};
        //测试希尔排序速度,给80000个数据,测试
        //创建一个80000个随机的数组
        int[] arr = new int[80000];
        for (int i = 0;i < 80000;i ++) {
            //会生成一个[0,8000000]的数
            arr[i] = (int)(Math.random() * 8000000);
        }
        //System.out.println("最开始的数组为:" + Arrays.toString(arr));
        Date date1 = new Date();
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date1Str = simpleDateFormat1.format(date1);
        System.out.println("排序前的时间:" + date1Str);
        //测试希尔排序
        shellSort(arr);
        Date date2 = new Date();
        String date2Str = simpleDateFormat1.format(date2);
        System.out.println("排序后的时间:" + date2Str);
    }
    public static void shellSort(int[] arr) {
        int temp = 0;
        //设置每次的步长,如第一次分为五组,则步长为5
        for (int gap = arr.length / 2;gap > 0;gap /= 2) {
            for (int i = gap;i < arr.length;i ++) {
                //遍历每组的元素(gap组,每组**个元素,步长gap)
                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;
                    }
                }
            }
        }
    }
}

不推荐原因:未使用到插入排序的思想,而是使用的冒泡排序思想,导致运行速度负提示。

代码实现移动法(推荐使用)

package sort;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ShellSort {
    public static void main(String[] args) {
        //int[] arr1 = {8,9,1,7,2,3,5,4,6,0};
        //测试希尔排序速度,给80000个数据,测试
        //创建一个80000个随机的数组
        int[] arr = new int[80000];
        for (int i = 0;i < 80000;i ++) {
            //会生成一个[0,8000000]的数
            arr[i] = (int)(Math.random() * 8000000);
        }
        //System.out.println("最开始的数组为:" + Arrays.toString(arr));
        Date date1 = new Date();
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date1Str = simpleDateFormat1.format(date1);
        System.out.println("排序前的时间:" + date1Str);
        //测试希尔排序
        shellSort(arr);
        Date date2 = new Date();
        String date2Str = simpleDateFormat1.format(date2);
        System.out.println("排序后的时间:" + date2Str);
    }
    public static void shellSort(int[] arr) {
        //设置每次的步长,如第一次分为五组,则步长为5
        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;
                    }
                    //当退出循环之后,就给temp找到了插入的位置
                    arr[j] = temp;
                }
            }
        }
    }
}

笔记源自:韩顺平数据结构与算法

你可能感兴趣的:(数据结构与算法)