希尔排序的两种方式理解与比较

本文深入探讨希尔排序的两种实现方法——交换法和移位法,通过详细解释和比较,帮助读者理解这两种算法的原理及适用场景。希尔排序是一种高效的插入排序改进算法,利用增量序列进行排序,提高了排序效率。文章将分析两种方法的性能差异,并通过实例展示其排序过程。
   今天在看韩顺平老师的希尔排序算法时,老师提到希尔排序有两种方式:移位法和交换法。
   由于希尔排序是为了优化插入排序,但是老师在演示时,在排列80000条数据时,插入排序大约耗时5S,而移位法的希尔排序耗时约17S,交换法的希尔排序用时约1S。为什么会出现这么大差别呢?
   经过观察思考,发现移位法比交换法多了很多多余的步骤,那就是不断变化数值。
   两种方法的输出结果一样且正确,但是执行效率差别很大。以数组int[] arr = {8,9,1,7,2,3,5,4,6,0};为例, 两种方法的第一次分组操作基本相同,移位法在执行第二次分组操作时,此时间隔为5/2=2,第一轮,元素下标从2也就是第三个元素数字1开始,比较前面间隔为2的元素数字3,发现3比1大,因此发生直接移位;第二轮5<6所以不发生位移;第三轮,3>0,3和0移位,即此时数组的数据是[1, 5, 0, 6, 3, 8, 9, 4, 7, 2],根据循环再次和0前面的1比较1>0,所以1和0移位,此时[0, 5, 1, 6, 3, 8, 9, 4, 7, 2],由此可见,中间借助temp移动了两次,这个过程在数据量大的情况下非常消耗时间。
   对于交换法来说,同样是在这个位置,它的处理方法就比移位法灵活很多,首先它定义int temp = arr[j](此时j的值为4);即将此时结果存到temp中,然后直接与前面进行比较:3>0满足条件,将原本0的位置上的数字改成3,即此时数据是[1, 5, 3, 6, 3, 8, 9, 4, 7, 2],**继续循环,发现1和0比(注意此时循环判断条件不是判断3和1,而是判断temp和1,此时temp的值依然是0),1>0满足条件,因此将原本是3的位置上元素改成1,即[1, 5, 1, 6, 3, 8, 9, 4, 7, 2],回到循环,由于循环条件不满足,直接执行下一步,把temp的值赋给arr[j](此时j已经为0)**,此时[0, 5, 1, 6, 3, 8, 9, 4, 7, 2]。这个过程的元素temp只移动了一次。后面的过程与前面类似我不在赘述。
   总结:算法的魅力在于能把复杂的问题变得简单,而在程序中,虽然基本思想都是一样的,但是如果在算法中不合理去运用技巧,也可能“弄巧成拙”,这个例子就能说明了这一点。
   如果有什么错误的地方,还请各位批评指正,笔者在此谢谢大家的阅读。
   代码:
//交换法
public static void shellSort3(int[] arr) {
		int count = 1;
		int count2 = 1;
		for(int gap = arr.length/2;gap>0;gap/=2) {
			//从第gap个元素逐个对其所在的组进行直接排序插入
			System.out.println("第"+count+"次分组前数组信息"+Arrays.toString(arr));
			System.out.println("第"+count+"次分组开始");
			for(int i=gap;i<arr.length;i++) {
				System.out.println("\t"+"第"+count2+"轮开始");
				int j = i;
				int temp = arr[j];
				if(arr[j]<arr[j-gap]) {
					while(j-gap>=0 && temp<arr[j-gap]) {
						//移动
						arr[j] = arr[j-gap];
						j -= gap;
					}
					arr[j] = temp;
					System.out.println(Arrays.toString(arr));
				}
				System.out.println("\t"+"第"+count2+"轮结束");
				count2++;
			}
			System.out.println("第"+count+"次分组结束");
			System.out.println("第"+count+"次分组后数组信息"+Arrays.toString(arr));
			count++;
			count2 = 1;
			
		}	
		//System.out.println(Arrays.toString(arr));
	}
//移位法
public static void shellSort2(int[] arr) {
		int temp = 0;
		int count = 1;
		int count2 = 1;
		int gap = 0;//用于记录每组元素个数以及步长
		for(gap = arr.length/2;gap>0;gap/=2) {
			System.out.println("第"+count+"次分组前数组信息"+Arrays.toString(arr));
			System.out.println("第"+count+"次分组开始");
			for(int i=gap;i<arr.length;i++) {
				System.out.println("\t"+"第"+count2+"轮开始");
				for(int j=i-gap;j>=0;j-=gap) {
					if(arr[j] > arr[j+gap]) {
						temp = arr[j];
						arr[j] = arr[j+gap];
						arr[j+gap] = temp;
						System.out.println(Arrays.toString(arr));
					}
				}
				System.out.println("\t"+"第"+count2+"轮结束");
				count2++;
				
			}
			System.out.println("第"+count+"次分组结束");
			System.out.println("第"+count+"次分组后数组信息"+Arrays.toString(arr));
			count++;
			count2 = 1;
		}	
		//System.out.println(Arrays.toString(arr));
	}
``交换法产生的结果图:
        ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190930003716333.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b2d1bzk2,size_16,color_FFFFFF,t_70)![在这里插入图片描述](https://img-blog.csdnimg.cn/20190930003810622.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b2d1bzk2,size_16,color_FFFFFF,t_70)移位法产生的结果图:
        ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190930003907863.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b2d1bzk2,size_16,color_FFFFFF,t_70)

![在这里插入图片描述](https://img-blog.csdnimg.cn/20190930003918296.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2d1b2d1bzk2,size_16,color_FFFFFF,t_70)                 


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值