希尔排序:
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序通过将比较的全部元素分为几个区域
来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,
算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。
排序思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部数据分组。所有距离为d1的倍数的数据放在同一个组中。先在各
组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量为1,即所有数据放在同一组中进
行直接插入排序为止。
希尔排序是不稳定的排序,时间复杂度为O(n^1.3-1.5).
增量序列的选择:
·最后一个增量必须为1;
·应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。
·一般的初次取序列的一半为增量,以后每次减半,直到增量为1。
先来复习一下插入排序的代码:
public static void insertSort(int[] arr) {
for (int x = 1; x < arr.length; x++) {
int j = 0;
int temp = arr[x];
for (j = x - 1; j >= 0; j--) {
if (arr[j] > temp) {
arr[j + 1] = arr[j];
}else {
break;
}
}
arr[j + 1] = temp;
}
对比来看希尔排序的程序实现:
import java.util.Arrays;
public class ShellSort {
public static void shell(int[] arr, int gap) {
int tmp = 0;
for (int i = gap; i < arr.length; i++) {
tmp = arr[i];
int j = 0;
// 按组比较,组里元素两两相隔增量位
for (j = i - gap; j >= 0; j = j - gap) {
if (arr[j] > tmp) {
arr[j + gap] = arr[j];
}else {
break;
}
}
// 组内交换
arr[j + gap] = tmp;
}
}
public static void shellSort(int[] arr) {
// 定义增量序列
int[] d = {5, 3, 1};
for (int i = 0; i < d.length; i++) {
shell(arr,d[i]);
}
}
public static void main(String[] args) {
int[] arr = {10, 25, 45, 8, 87, 47, 65, 20, 14,60};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
}
以上程序的输出结果是:[8, 10, 14, 20, 25, 45, 47, 60,65, 87]
以上程序运行过程是这样的:
可以看到,每一次排序后数组总比上一次有序,而这也是希尔算法优于直接插入排序的关键所在。