概述
希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因D.L.Shell于1959年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
- 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
- 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
该方法实质上是一种分组插入方法
算法过程描述
平均复杂度
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。
算法稳定性
由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。
示例代码
/**
* 希尔排序
* @author 吴庆龙
* Date: 2018/8/6
* Time: 9:34
*/
public class ShellSort {
public static void main(String[] args) {
int[] array = {7,3,2,4,1,8,0,9,5,6};
sort(array);
for (int i : array) {
System.out.print(i + " ");
}
System.out.println();
}
private static void sort(int[] array) {
// 定义初始增量
int increment = array.length / 2;
// 控制增量
while (increment > 0) {
// 控制分组切换
for (int elemIndex = increment; elemIndex < array.length; elemIndex++) {
// 已经排好序数组的最后一个元素(如果是普通插入排序,这里这是int k = j - 1)
int lastSortedElemIndex = elemIndex - increment;
int key = array[elemIndex]; // 要排序的元素
for (; lastSortedElemIndex >= 0 && key < array[lastSortedElemIndex] ; lastSortedElemIndex -= increment) {
array[lastSortedElemIndex + increment] = array[lastSortedElemIndex];
}
// 与插入排序类似
array[lastSortedElemIndex + increment] = key;
}
increment /= 2;
}
}
}
希尔排序只是针对插入排序的一个改进,分组之后还是进行的插入排序。