希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因D.L.Shell于1959年提出而得名。
算法原理
- 希尔排序把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1,整个数据恰好被分成一组,算法终止;
- 希尔排序是不稳定的排序算法;
- 总的来说:将整个待排序的序列按步长分割成若干个子序列分别进行直接插入排序,然后步长逐渐减小,最终构成一组有序记录;
- 本质上是插入排序的一种更高效的改善型算法;
分析
- 有n个数据的无序序列,在第一趟排序不妨设步长gap=n/2,这样每相隔n/2的数据组成一组,每组进行插入排序;
- 第二趟将gap再次缩小一半,即gap=n/4,继续对每组数据进行插入排序;
- 直至gap=1,此时相隔距离为1的数据组成一组,即只有一组,此时排序后算法结束;
时间复杂度
- 最好情况:希尔排序的好坏与步长选择有很多关系,目前还没有得出最好的步长选择;
- 最坏情况:O(nn*logn)~O(n2)
代码实现
public class ShellSort {
public static void shellSort(int[] arr) {
if (arr == null || arr.length <= 1) {
return;
}
int gap = arr.length / 2;
while (gap >= 1) {
for (int i = gap; i < arr.length; i++) {
int j;
int tmp = arr[i];
for (j = i - gap; j >= 0 && tmp < arr[j]; j -= gap) {
arr[j + gap] = arr[j];
}
arr[j + gap] = tmp;
}
gap = gap / 2;
}
}
public static void main(String[] args) {
int[] arr = {67,43,7,93,2,66,7,8};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
}
//输出结果:[2, 7, 7, 8, 43, 66, 67, 93]