此文章建立在最希尔排序稍微有些了解。
这里有一个Shell排序的算法演示
/******* Shell Sort ********/
/******* Data: 2012.1.7 ********/
/******* Author: 1 i f e ********/
#include<stdio.h>
int main()
{
int data[100],temp,i,j,n;
n=100;
for(i=1;i<n;i++)
{
temp =data[i];
for(j=i;j>0&&data[j]<data[j-1];j--)//这里有一点,小技巧就是说,插入排序建立在,已经排好的序列之上,所以那么既然data[j]<data[j-1]不成立,说明这个说这个数已经大于了前面所有已排序好的数
{
data[j]=data[j-1];
}
data[i]=temp;
}
}
这是基本的插入排序,它的时间复杂度最坏是O(n!),但是开销花在数据移动上。
插入排序在什么时候会很快?当整个数组大部分(这个大部分,是对于全局而言)都已经排序好了,插入排序秩序进行添加只需移动较少的数据即可完成。插入排序对于后期数据的维护性非常好。
Shell排序是分组的插入排序。分组有局部分组,还有就是间隔step实现全局分组
如果是局部分组即1~step,step~2*step,。。。。这对于插入排序是毫无意义的,假如要实现从小到大排序,第一组就有可能出现了这个数组的最大的数,想通过最后一组,可能出现来了这个数组中的最小值。所以不可以提升性能。
而间隔性的step分组即{0,step,2*step。。。}为一组。{1,1+step,1+2*step。。。}为一组。实现的全局的大致排序,对插入排序的下一次,提供了基础。
void ShellSort(int *data,int n)
{
int i,k,j=-1,step,temp; //关于这里为何为j=-1,因为在调试的时候发现,while循环执行,会先将j+1。
step=n/2;
while(step>0) //这里则是进行对step判断,循环step>0
{
while(++j<step) //这里是分了多组的插入排序,循环j<step
{
for(i=j+step;i<n;i+=step) //这里则是一组具体的插入排序,循环i<n
{
temp=data[i];
for(k=i;k>=j+step&&data[k]<data[k-step];k-=step) //对照上面的插入排序,是似曾相识的。区别在这里k>=j+step,因为,分为多组,每一组以j开头,所以对比下发现,因为上面的插入排序只有一组,所以省略了而已。因而对于上面而言,规范的书写是i=(0+step)
data[k]=data[k-step];
data[k]=temp;
}
}
j=-1;
step=step/2;
}
对于希尔排序,假如n=8,step=4完成后可能没有完成功能即可能相距4的还没有排序好。就进行了step=2的排序。这里可能会造成错误。
例如:44 55 12 42 94 18 6 67
第一次(即while(step>0)完成一趟循环):44 18 6 42 94 55 12 67 step=4(同一种颜色为一组)
第二次:6 18 44 42 12 55 94 67 step=2(同一种颜色一组,可以看出粉颜色这一组,部分插入排序没做好,44还在12之前,所以还要进行step=2的一次排序)
因此,对于这种解决方法
有两种可以解决:1、设一个标志位,如果发生过移动,就再重复一遍,直至不发生移动 。
2、也是我要采用的方法
void ShellSort(int *data,int n)
{
int i,k,j=-1,step,temp; //关于这里为何为j=-1,因为在调试的时候发现,while循环执行,会先将j+1。
step=n/2;
while(step>0) //这里则是进行对step判断,循环step>0
{
while(++j<step) //这里是分了多组的插入排序,循环j<step
{
for(i=j+step;i<n;i+=step) //这里则是一组具体的插入排序,循环i<n
{
temp=data[i];
for(k=i;k>=j+step&&temp<data[k-step];k-=step) //对照上面的插入排序,是似曾相识的。区别在这里k>=j+step,因为,分为多组,每一组以j开头,所以对比下发现,因为上面的插入排序只有一组,所以省略了而已。因而对于上面而言,规范的书写是i=(0+step)
data[k]=data[k-step];
data[k]=temp;
}
}
j=-1;
step=step/2;
}
for(k=i;k>=j+step&& temp<data[k-step];k-=step)
注意加红的部分,很简单的更改