插入排序之希尔排序-(带图详细)

一、什么是希尔排序

希尔排序(Shell’s Sort)又称“缩小增量排序”,它也是插入排序的一种,但时间效率上较直接插入排序有较大的改进。


希尔排序是对直接插入排序算法的一种改进,对直接插入排序算法分析,其时间复杂度为O(n2),若待排序序列正序的时候时间复杂度为O(n),由此可知,待排序序列基本有序时其效率高。
从另一方面看,直接插入排序算法简单,若待排序序列元素少时,也不需要进行大量的移动和比较,因此其效率也高。

二、算法思想

①先将整个待排序序列分割成若干个子序列,②然后分别进行【直接插入排序】,③然后缩小增量,在执行①②步,直到缩小至1,再执行④
④待整个序列中的记录“基本有序”再对整个序列进行一次直接插入排序。

算法的思想的目的就是为了让序列元素减少或者基本有序,这样就可以发挥直接插入排序的最高效率。

三、实例讲解

有个待排序序列为:【4,10,34,54,12,3,1,55,15,13】,需要对此序列进行希尔排序。
算法思想中第一步:
将整个待排序序列分成若干个子序列。对于初学者来说一般想分割序列的方式就是平均分成若干个序列,例如:1-5为一个序列,6-10为第二个序列。
希尔排序采取的是相隔某个“增量”的记录组成的子序列。例如:增量为5,则第1个元素和第6个元素为一个子序列,第2个元素和第7个元素为一个子序列,等等。如图:相同颜色为一个子序列。
在这里插入图片描述

算法思想中第二步:
然后分别分割后的五个子序列进行直接插入排序。
在这里插入图片描述
此时原始序列为:
在这里插入图片描述

注意:在很多文章中讲解的是对子序列以次进行直接插入排序,但是我在代码实现过程中发现,这个过程并不是一个子序列全部完成排序后再进行下一个子序列的排序,而是以元素为基准,第一个序列第一个元素,第二个序列第一个元素,第三个序列第一个元素;第一个序列第二个元素,第二个序列第二个元素,第三个序列第二个元素

算法思想中第三步:
缩小增量为:2。
执行算法思想第一步: 分割成若干子序列
在这里插入图片描述
执行算法思想第二步: 对每个子序列进行直接插入排序
在这里插入图片描述
此时原始序列为:
在这里插入图片描述
算法思想中第四步:
此时增量为:1 ,原始序列基本有序,直接对该序列进行直接插入排序即可。

小结:算法思想为四步,只要我们记住这四步就可以理解希尔排序的思想,至于实例讲解和代码实现是为了加深对希尔排序的理解。

四、算法分析

时间复杂度

希尔排序的时间复杂度介于O(n1.3) 和O(n2)之间,取决于,增量的选取,但至今仍没有一种最好的选取增量的方法。 需注意的是,应使增量没有除1之外的公因子,而且增量最后必须等于1。

空间复杂度

O(1)

稳定性

不稳定的排序

五、代码实现

#include<stdio.h> 
void Print(int array[],int len){
	for(int i=0;i<len;i++){
		printf("%d ",array[i]);
	}
	printf("\n");
} 
/**希尔排序 
*算法思想
* 1.希尔排序是针对直接插入排序的优化 
* 2.对直接插入排序算法分析:
*	 序列基本有序时移动次数少 排序效率高 
*	 序列长度短时排序移动次数和比较次数都少 排序效率高 
* 3. 希尔排序是首先将待排序序列分割成多个长度短的子序列然后使用直接插入排序
*	 但并不是直接将待排序序列平均分成若干个子序列,而是相隔某个增量值(δk)为一个子序列 
* 4. 然后整个序列就基本有序了,在使用直接插入排序 (增量为1) 
*/
void ShellSort(int array[],int len) {
	int i,j;
	int dk = len/2;  //增量 k (增量任意取值,我这里每次取序列长度的一半) 
	while(dk>=1) {  //增量为1即直接插入排序 
		/*直接插入排序变体开始*/ 
		//(将代码中的dk替换成1则和直接插入排序是一样的)  
		for(i=dk;i<len;i++){  //易错此处是i++ 并不是 i+=dk 
			int tem = array[i];
			for(j=i-dk;j>=0&&tem<array[j];j-=dk){
				array[j+dk] = array[j];
			}
			array[j+dk] = tem;
		}
		/*直接插入排序变体结束*/ 
		dk/=2;
	}
}
int main(){
	int array[]={4,10,34,54,12,3,1,55,15,13};
	// 44 4 26
	//31 3
	//38 10 
	int len = sizeof(array) / sizeof(int);
	printf("初始序列:\n");
	Print(array,len);
	ShellSort(array,len);
	printf("排序后序列:\n");
	Print(array,len);
}

六、运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小陈没烦恼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值