Shell(希尔)排序的分析和比较

此文章建立在最希尔排序稍微有些了解。

这里有一个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)

注意加红的部分,很简单的更改

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值