算法简介:
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;
希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序,实质上是一种分组插入法。
算法思想:
希尔排序是特殊的插入排序,直接插入排序每次插入前的遍历步长为1,而希尔排序是将待排序列分为若干个子序列,对这些子序列分别进行直接插入排序,当每个子序列长度为1时,再进行一次直接插入排序时,结果一定是有序的。常见的划分子序列的方法有:初始步长(两个子序列相应元素相差的距离)为要排的数的一半,之后每执行一次步长折半。
希尔排序的过程演示如下:
动图演示
代码实现
#include <stdio.h>
int main(int argc, char *argv[])
{
srand(time(NULL));//设置随机数种子
int i,j,k,m,temp,len;
int a[15]={0};//定义一个随机数数组并输出
printf("排序前:");
for(i=0;i<15;i++)
{
a[i]=rand()%99;
printf("%2d ",a[i]);
}
putchar('\n');
len=sizeof(a)/sizeof(a[0]);
for(m=len/2;m>0;m/=2)//m为每组成员间隔
{
for(i=0;i<m;i++)//将所有组排序一次
{
for(j=i+m;j<len;j+=m)//j定位到组中后一位元素
{
temp=a[j];//将值存储一次
k=j-m;//k是i位置下标
while(k>=0&&a[k]>temp)//进行交换数据
{
a[j]=a[k];
a[k]=temp;
k-=m;
}
}
}
}
printf("排序后:");
for(i=0;i<15;i++)//遍历数组
{
printf("%2d ",a[i]);
}
putchar('\n');
return 0;
}
时间复杂度
在最优的情况下,希尔排序的时间复杂度为O(n1.3),在最差的情况下,希尔排序的时间复杂度为:O(n2)。 希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。
稳定性
由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。