排序——希尔排序

一、基本介绍

? 希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更加高效的版本,也称为缩小增量排序。

? 在排序过程中,把待排序数据按照一定增量分组,对每组数据使用直接插入排序算法进行排序;随着增量的减小,每组的数据越来越多;当增量减少为 1 时,整个数据被分为一组,算法终止,排序完成。

二、图解过程

对数组[ 8, 9, 1 , 7, 6 , 5 , 3 , 4 , 2 , 0 ] 从小到大排序过程如下:

  1. 初试时共有 10 个元素

    排序——希尔排序

  2. 第一次排序

    初始步长设置为 10 / 2 = 5,分为 5 个组。即 [8 , 5],[9 , 3],[1 , 4],[7 , 2],[6 , 0],如下图所示,相同颜色为一组,然后同一组数据进行直接插入排序,排序后数组为[5 , 3 , 1 , 2 , 0 , 8 , 9 , 4 , 7 , 6]。

    排序——希尔排序

  3. 第二次排序

    步长设置为 5 / 2 = 2,分为 2 个组。即[5 , 1 , 0 , 9 , 7],[3 , 2 , 8 , 4 , 6],如下图所示,相同颜色为一组,然后同一组数据进行直接插入排序,排序后为 [0 , 2 , 1 , 3 , 5 , 4 , 7 , 6 , 9 ,8]。

    排序——希尔排序

  4. 第三次排序

    步长设置为 2 / 2 = 1,分为一个组,最后对着组数据进行插入排序即可获得最终排序完成的结果。

    排序——希尔排序

从以上分析可知,希尔排序的排序次数是当增量为 1 时结束。每一次分组之后在组内在此进行排序,直到最终排序完成。

三、代码实现

? 希尔排序实现排序时,对于每一组的数排序可以采用交换法,或者是移动法插入。因为交换法的效率并不高,所以下面代码仅展示移动法。

public static void shellSort(int[] arr) {
    if (arr == null || arr.length < 2) {//数组为空或者长度为1直接返回
        return;
    }
    for (int gap = arr.length / 2; gap > 0; gap /= 2) {//初始步长(增量)为数组长度的一半
        //创建一个循环,对每一个组的元素进行排序
        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;//插入元素
            }
        }
    }
}

相关推荐