1.原理
希尔排序又称为缩小增量排序,是一种插入排序,排序速度比直接插入排序更加快捷。
对于长度为n的待排序数组a,希尔排序的基本思路如下:
A.选取整数gap(0<gap<n),将所有距离为gap的元素分为一组,总计有gap组;
B.对各个数组进行直接插入排序,数组变得稍微有序;
C.重复步骤A和B,对数组不断进行分组和排序,直至gap=1,此时对整个数组进行直接插入排序,排序完成。
2.实例
待排序数组a:[8, 1, 4, 2, 7, 0, 9, 6, 3, 5]
第一次: 第二次:
gap=5,数组分类如下: gap=2,数组分类如下:
a:[8, 1, 4, 2, 7, 0, 9, 6, 3, 5] a:[0, 1, 4, 2, 5, 8, 9, 6, 3, 7]
A: 8 0 A: 0 4 5 9 3
B: 1 9 B: 1 2 8 6 7
C: 4 6 数组分为2组,对每组进行直接插入排序,结果如下:
D: 2 3 A: 0 3 4 5 9
E: 7 5 B: 1 2 6 7 8
数组分为5组,对每组进行直接插入排序,结果如下: a:[0, 1, 3, 2, 4, 6, 5, 7, 9, 8]
A:0 8
B: 1 9 第三次:
C: 4 6 gap=1,即对整个数组进行直接插入排序:
D: 2 3 a:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
E: 5 7
a:[0, 1, 4, 2, 5, 8, 9, 6, 3, 7]
3.代码
1 public class ShellSortTest { 2 // 遍历数组 3 public static void printAll(int[] a) { 4 for (int value : a) { 5 System.out.print(value + "\t"); 6 } 7 System.out.println(); 8 } 9 10 //希尔排序 11 public static void shellSort(int a[]) { 12 int gap = a.length / 2; //取初始步长为n/2 13 while (gap>=1) { 14 // 把距离为 gap 的元素编为一个组 15 for (int i = gap; i < a.length; i++) { 16 int temp = a[i]; //待插元素 17 int j = i - gap; 18 19 // 对距离为 gap 的元素组进行直接插入排序 20 while ( j >= 0 && temp < a[j]) { 21 a[j + gap] = a[j]; //元素后移 22 j = j - gap; 23 } 24 a[j + gap] = temp; //在空出的位置插入待插元素 25 } 26 System.out.format("gap="+gap+":"+"\t"); 27 printAll(a); 28 gap = gap / 2; // 减小增量 29 } 30 } 31 public static void main(String[] args) { 32 int a[]= { 8, 1, 4, 2, 7, 0, 9, 6, 3, 5 }; 33 System.out.print("排序前:\t"); 34 ShellSortTest.printAll(a); 35 ShellSortTest.shellSort(a); 36 System.out.print("排序后:\t"); 37 ShellSortTest.printAll(a); 38 } 39 }
4.时间复杂度
希尔排序的时间复杂度与步长的选取有关,例如希尔增量时间复杂度为O(n²),而Hibbard增量的希尔排序的时间复杂度为O(),
希尔排序时间复杂度的下界是n*log2n。