排序实现与分析 -- 希尔排序

希尔排序

按理解的话,其实希尔排序就是插排的升级版,他的思想是:对需要排序的数据进行分组,通过每组的插排使得组内有序,从而整体接近有序,此时对整体进行插排就很快(在插排中说过,插排,数据越有序速度越快)
在这里插入图片描述

但是要注意的一点是,分组不是常规的认为那样分组(如上所示),上图在红蓝组内有序后,整体数据如下
在这里插入图片描述
如此一看,整体并非有序,所以应该如下进行分组
在这里插入图片描述
组内有序后 ,整体如下
在这里插入图片描述
整体接近有序,达到要求希尔排序是结合了一定的数学问题的,数学问题给出了分组的方式,原理这里不做探讨,给出,尽量以素数分组,且最后一次分组每组个数为1,也就是最后一次是对整体进行排序,例如我在测试的时候用的数列就是{ 5, 3, 1 }.


代码实现

这里要说的是,如上数据,分两组,第一组元素就是第一个,第三个,第五个,第七个,第二组是第二个,第四个,第六个,第八个;逐步后移两步,由此可知,分几组就是后移几步

void shell(int *arr, int size, int step/*步数*/)//一趟希尔,插排变式
{
	int tmp,i,j;
	for(i = step/*组内第一个元素默认有序,从第二个开始*/;i < size; i += step)
	{
		tmp = arr[i];
		for(j = i - step;j >= 0;j -= step)//注意上一个元素是当前序号减去步数,而非-1
		{
			if(arr[j] <= tmp)
				break;//找到位置跳出
			else
				arr[j + step] = arr[j];//后移
		}
		arr[j + step] = tmp;//插入
	}
}
void shellsort(int *arr,int size)//希尔排序
{
	int d[] = {5,3,1};//分组数数列(示例)
	for(int i = 0;i < sizeof(d)/sizeof(d[0]);i++)//循环遍历数列,进行每一趟的希尔
	{
		shell(arr,size,d[i]);
	}
}

时间复杂度、空间复杂度以及稳定性
  1. 时间复杂度
    先说说希尔排序与直接插排相比优点在哪。
    假设一百个数据,直接插排根据O(n^2)计算,要进行10000次排序,我们100数据分十组组插排,每组组内有序排序十组就是进行101010=1000次,然后再进行全排,这时候因为组内有序,我们假设全排时间复杂度退化为O(n ^1.5),全排就需要1000次,这样总共需要2000次,相比直接插排快了不少,以此提速,我们的分组数列相比数据量的增加而言,增加是十分少的,所以可以忽略,数学方法归纳,希尔排序的时间复杂度一般为O(n ^1.3)

  2. 空间复杂度
    因为忽略分组数列的增长速度,我们的空间复杂度就是O(1)

  3. 稳定性
    正如上次讲到,希尔排序,跨越式分组,并且进行交换,所以他是不稳定的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值