希尔排序:不稳定排序
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量



一般的初次取序列的一半为增量,以后每次减半,直到增量为1。
比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。不像直接插入多次比较才能插入一个元素。
希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n²),而Hibbard增量的希尔排序的时间复杂度为O(


package test;
import java.util.Arrays;
/*
* 希尔排序:
* 把数组按照增量分组,分别对每个分组进行直接插入排序。
* 在新的数组中缩小增量,继续分组排序,直到增量为1.
* 这样就可以将数组中的元素排好序了。
*
* 希尔排序是改进的插入排序。
* 直接插入排序在需要经过多次的比较才可应交换一个元素
* 希尔排序经过分组,可以实现在一次比较中交换多个元素
* 时间复杂度与增量选择有关,最差是O(nlog2n),比直接插入的O(n^2)好
*/
public class shellSort {
//希尔排序:首先将数组按增量s分组,在每一个分组进行直接插入排序
static void ShellSort(int a[], int len) {
//初始增量s取值为len/2,逐渐缩小增量,直到增量为1表示已经全部排好序
for(int s = len/2; s >= 1; s /= 2) {
//增量为s,那么就有s个分组。对每个分组进行排序
for(int i = 0; i < s; i++ ) {
sort(a,i,s,len);
}
}
}
//对每个分组进行直接排序,基本实现与直接插入一致,只是下标增量为s,不是为1
//其中i表示分组的起始小标,s表示增量
static void sort(int a[], int i, int s, int len) {
//默认分组第一个元素A[i]是排好序的,从分组的第二个元素A[i+s]开始进行插入排序
for(int j = i+s; j < len; j += s) {
//如果待插入元素小于排好序部分的最后一个元素,表明待插入元素不是直接插入排好序部分的后面
if(a[j] < a[j-s]) {
//记录待插入元素
int temp = a[j];
//需要将排好序的部分从后往前都右移一位,直到找到比待插入元素小的元素
while(j-s >= 0 && a[j-s] > temp) {
//元素往后移动一位
a[j] = a[j-s];
j -= s;
}
//将待插入元素插入
a[j] = temp;
}
}
}
public static void main(String args[]) {
int a[] = new int[]{4,2,6,8,3,7,9,333,555,22,4,6,88,4,3,4456,32,7,8,64};
ShellSort(a,a.length);
System.out.println(Arrays.toString(a));
}
}