一、原理
希尔排序是直接插入排序的一种更高效的改进版本。它把记录按下标的一定增量进行分组,然后对每组使用直接插入排序;随着增量逐渐减少每组中包含的元素越来越多,也越来越有序,当增量减到为1时,整个序列就是一组,排序结束。
二、代码实现
package com.jdk8.SortTest;
import java.util.Arrays;
public class ShellSort {
public static void display(int[] arrays){
for(int i = 0;i < arrays.length;i++){
System.out.print(" " + arrays[i] + " ");
}
}
public static void main(String[] argss){
int[] arrays = {3,9,63,93,72,15,27,86};
int parition = 2;
System.out.println("排序前的数据为:");
display(arrays);
shellSort(arrays,parition);
System.out.println();
System.out.println("排序后的数据为:");
display(arrays);
}
public static int[] shellSort(int[] arrays,int parition){
// i表示希尔排序中的第n/parition+1个元素
// j表示希尔排序中从0到n/parition+1的元素
// r表示希尔排序中n/parition+1个元素的值
int i, j, r, key;
for(r = arrays.length / parition; r >= 1; r = r / 2) {
for(i = r; i < arrays.length; i++) {
key = arrays[i];
j = i - r;
// while进行一轮排序
while(j >= 0 && key < arrays[j]) {
arrays[j+r] = arrays[j];
j -= r;
}
arrays[j+r] = key;
}
}
return arrays;
}
}
运行结果如下:
排序前的数据为:
3 9 63 93 72 15 27 86
排序后的数据为:
3 9 15 27 63 72 86 93
三、和直接插入排序对比
修改下main函数,修改如下:
public static void main(String[] argss){
int[] arrays = new int[500000];
for(int i = 0;i < 500000;i++){
arrays[i] = i + 1;
}
int parition = 5;
long start = (new Date()).getTime();
shellSort(arrays,parition);
long end = (new Date()).getTime();
System.out.println("希尔排序消耗时间为"+(end - start));
}
此为正序,对插入排序的main做类似处理。运行五次时间差分别如下:
直接插入排序:
15 0 0 0 0
希尔排序:
16 15 16 16 15
倒序情况下:
直接插入排序:
47841 47362 47177 47327 47559
希尔排序:
32 31 32 32 31
注:设备为: 处理器为i5-8250U,内存8.00G,64为操作系统。
当为正序时直接插入排序比希尔排序快,但是当时倒序时希尔排序比直接快速排序快很多,平均情况下比直接插入排序快。
四、复杂度分析
4.1、时间复杂度分析
希尔排序的时间复杂度:O(n^(1.3—2))
4.2、空间复杂度
希尔排序的临时变量所占用的空间不随处理数据n的大小改变而改变,即空间复杂度为O(1)。
五、稳定性
希尔排序是不稳定排序。