希尔排序

过程

希尔排序可以说是插入排序的一种变种。无论是插入排序还是冒泡排序,如果数组的最大值刚好是在第一位,要将它挪到正确的位置就需要 n - 1 次移动。也就是说,原数组的一个元素如果距离它正确的位置很远的话,则需要与相邻元素交换很多次才能到达正确的位置,这样是相对比较花时间了。

希尔排序就是为了加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序。

希尔排序的思想是采用插入排序的方法,先让数组中任意间隔为 h 的元素有序,刚开始 h 的大小可以是 h = n / 2,接着让 h = n / 4,让 h 一直缩小,当 h = 1 时,也就是此时数组中任意间隔为1的元素有序,此时的数组就是有序的了。

动图展示

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* 希尔排序
*/

public class ShellSort {

public static int[] shellSort(int[] arr) {
if (arr == null || arr.length < 2) {
return arr;
}
int n = arr.length;
//step:步长
for (int step = n / 2; step > 0; step /= 2) {
//对一个步长区间进行比较 [step,arr.length)
for (int i = step; i < arr.length; i++) {
int value = arr[i];
int j;
//对步长区间中具体的元素进行比较
for (j = i - step; j >= 0 && arr[j] > value; j -= step) {
//j为左区间的取值,j+step为右区间与左区间的对应值。
arr[j + step] = arr[j];
}
//此时j为一个负数,[j + step]为左区间上的初始交换值
arr[j + step] = value;
}
}
return arr;
}

public static void main(String[] args) {
int[] arr = {2, 5, 3, 1, 4, 6};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}

}

性质:

  1. 时间复杂度:O(nlogn)
  2. 空间复杂度:O(1)
  3. 非稳定排序
  4. 原地排序

参考