前面的直接插入排序和折半插入排序在基本有序的时候,效率最高,在待排序的记录比较少的时候效率较高.
个人觉得希尔排序刚好针对上面俩个问题,通过大间隔排序使整体基本有序,从而使得排序效率变高了
之前的插入排序可以分为通过比较寻找插入位置,通过将插入位置后的元素后移,然后将元素插入有序序列中,但是每次只能移动一次,a[j+1] = a[j],希尔排序和前面俩种插入排序不一样的是比较一次会移动一大步(len)
基本思想:
先将整个待排序的序列分割成若干个子序列,分别进行直接插入排序(间隔不为1 ),每次排序间隔逐渐变小,当间隔为1的时候,整个序列基本有序了,再对全体序列进行一次间隔为1的直接插入排序
于是需要定义一个递减增量len,对整个序列进行间隔为len的插入排序,
len需要互质,不然会有情况会有发生len>1的时候不排序的情况发生。
(注意,这样的话希尔排序是不是和在链式存储结构上实现的,因为链表找到其相隔len的元素是比顺序存储结构复杂的多的)
from https://blog.nowcoder.net/n/2b9bfa8c73524827bd3ac9fdc75c52d8
代码如下:
其复杂度是和间隔len相关的,最坏的情况可以认为是O(n^2), 空间复杂度为O(1),但是不是稳定的排序
//希尔排序
void shellA(int a[], int n){
int k, i, j;
int tmp;
int len = n;
do{
len = len/3+1;
for(k=0; k<len; k++){//先将数组分为以len为间隔的若干小组
for(i=k+len; i<n; i+=len){//注意是以len为间隔的直接插入排序
tmp = a[i];
for(j=i-len; j>=0 && tmp<a[j]; j-=len){
a[j+len] = a[j];
}
a[j+len] = tmp;
}
}
// printf("%d\n", len);
// skipArr(a, n);
}while(len>1);
}