希尔排序详解

八大排序算法中,有两种插入排序,直接插入排序和希尔排序,下面我们来介绍希尔排序。

希尔排序

希尔排序又叫做缩小增量排序。

1、基本思想

设待排序元素序列有n个元素,首先取一个整数increment(小于n)作为间隔将全部元素分为increment个子序列,所有距离为increment的元素放在同一个子序列中,在每一个子序列中分别实行直接插入排序。然后缩小间隔increment,重复上述子序列划分和排序工作。直到最后取increment=1,将所有元素放在同一个子序列中排序为止。

2、希尔排序举例

1)给出一个数据列:
希尔排序详解_第1张图片
2)第一趟取increment的方法是:n/3向下取整+1=3(关于increment的取法之后会有介绍)。将整个数据列划分为间隔为3的3个子序列,然后对每一个子序列执行直接插入排序,相当于对整个序列执行了部分排序调整。图解如下:
希尔排序详解_第2张图片
3)第二趟将间隔increment= increment/3向下取整+1=2,将整个元素序列划分为2个间隔为2的子序列,分别进行排序。图解如下:
希尔排序详解_第3张图片
4)趟把间隔缩小为increment= increment/3向下取整+1=1,当增量为1的时候,实际上就是把整个数列作为一个子序列进行插入排序,图解如下:
希尔排序详解_第4张图片
5)直到increment=1时,就是对整个数列做最后一次调整,因为前面的序列调整已经使得整个序列部分有序,所以最后一次调整也变得十分轻松,这也是希尔排序性能优越的体现。

注:增量increment的取值方法:

  • 最初shell提出取increment=n/2向下取整,increment=increment/2向下取整,直到increment=1。但由于直到最后一步,在奇数位置的元素才会与偶数位置的元素进行比较,这样使用这个序列的效率会很低。
  • 后来Knuth提出取increment=n/3向下取整+1

3、代码实现

//希尔排序
public static void shell_sort(int[] numbers,int start, int end) {  //待排序数组,数列起点,数列终点
    int increment = end - start + 1;    //初始化划分增量
    int temp = 0;
    do {    //每次减小增量,直到increment = 1
        increment = increment / 3 + 1;
        for (int i = start + increment; i <= end; ++i) {    //对每个划分进行直接插入排序
            if (numbers[i - increment] > numbers[i]) {
                temp = numbers[i];
                int j = i - increment;
                do {    //移动元素并寻找位置
                    numbers[j + increment] = numbers[j];
                    j -= increment;
                } while (j >= start && numbers[j] > temp);
                numbers[j + increment] = temp;  //插入元素
            }
        }
    } while (increment > 1);
}
	
//测试主程序
public static void main(String[] args) {
    int[] array = {4,8,2,1,6,3,4,9};
    shell_sort(array,0,array.length-1);
    for(int a : array) {
        System.out.println(a);
    }
}

4、希尔排序性能分析

1)由于相等的两个元素在排序时可能会发生交换,故希尔排序是一种不稳定的排序算法。
2)相比于直接插入排序,希尔排序有较好的排序效率,排序所用时间比直接插入排序小很多。

源码地址:https://github.com/Abel-LiuJinQuan/Sort
本文部分内容转自:https://blog.csdn.net/weixin_37818081/article/details/79202115

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