希尔排序

介绍

希尔排序又称缩小增量排序,基本思想为:先将待排序列分割成若干子表,把相隔某个增量的记录组成一个子表,对各个子表分别进行直接插入排序,当整个表已基本有序的时候,再对整个表进行一次直接插入排序。

希尔排序的过程如下:先取一个小于n的步长d1,把表中的全部记录分成d1组,所有距离为d1的倍数的记录放在同一组,在各组内进行直接插入排序;然后取第二个步长d2<d1,重复上述过程,直到所得到的dt=1,即所有记录已放在同一组中,在进行直接插入排序,由于此时已经具有较好的局部有序性,故可以很快得到最终结果。
希尔排序的时间复杂度大概在O(n^1.3),在最坏的情况下会到达 O( n^2 )。

算法实现

实现方法1(我编写的我认为容易理解的希尔排序实现算法)

我们初始时,令增量d为数组大小的一半,之后每次增量折半,直到小于1的时候,会停止。也就是最后一次循环时,增量为1,相当于直接插入排序,但此时因为已经基本有序,所以移动的元素非常少了。

每个增量dt将元素分成dt组,每组的元素进行直接排序。

#include <stdio.h>
#include <windows.h>
#include <stdint.h>
void Hill_sort(int a[],int size);
int main()
{
int k;
int num[9]={9,8,7,4,6,5,1,2,3};
int sortsize=sizeof(num)/sizeof(num[0]);
Hill_sort(num,sortsize);
for(k=0;k<sortsize;k++)
printf("%d\n",num[k]);
system("pause");
return 0;
}
void Hill_sort(int a[],int size)
{
int i,j,k;
int d;
int temporary;
for(d=size/2;d>=1;d=d/2)
{
printf("\nd=%d:",d);
for(k=0;k<d;k++)
for(i=k;i<size;i+=d)
{
printf("\ni=%d:",i);
temporary=a[i];
for(j=i-d;a[j]>temporary&&j>=0;j=j-d)
{
a[j+d]=a[j];
printf("j=%d;",j);
}
a[j+d]=temporary;

}
}
}

实现效果

什么是希尔排序?_算法

上述程序是我按照我的思路写的,我认为是最容易理解,但效率不是最高的,程序中使用了四重循环。

实现方法2(网络上最常见的希尔排序算法)

网络上最常见的希尔排序算法的实现,如下所示。

void shell_Sort(ElemType A[],int n)
{
int i, j, dk;
for (int dk = n / 2; dk >= 1; dk--)
for(int i=dk+1;i<=n;i++)
if (A[i] < A[i - dk])
{
A[0] = A[i];
}
for (int j = i - dk; j > 0 && A[0] < A[j]; j -= dk)
A[j + dk] = A[j];
A[j + dk] = A[0];
}

扩展

数据结构或者说算法,只要理念是一样的,实现方法因人而异,我们不需要纠结到底哪一个效率最高,因为只要是按照此算法理解实现的程序,大致的算法时间复杂度都大同小异,关键是我们是否能学会此算法,而判断我们学会算法的标准就是自己能写出符合此算法思路的实现程序,如果能和网络上其他人写的不一样,反而是一种好事。所以读者可以仔细理解一下上面的两个程序,来理解一下希尔排序的理念和优点。

后续

欢迎关注公众号:物联网知识