必须会的排序算法--(2)希尔排序

本文详细介绍了希尔排序算法,一种高效的插入排序改进版本。通过逐步减少步长对数组分组并进行直接插入排序,使得数据接近有序状态,从而提高排序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 :希尔排序概括:

/*
摘自维基百科:
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率
但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位
*/

二:算法实现:

/*
摘自维基百科:
希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。
这样可以让一个元素可以一次性地朝最终位置前进一大步。
然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,
但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。
*/

三:按照步长分组:
1.原数组数组a[10] ={10,9,8,7,6,5,4,3,2,1}
2.按照n/2步长:即分为5组。
/*
 第一次分组(一列一组):  
10  9  8  7  6 
 5  4  3  2  1
结果:(10,5) (9,4) (8,3) (7,2) (6,1) 五组
*/


3.对分组进行直接插入排序
/*
第一次排序:
5   	4  	3 	2  	1
10 	9   	8  	7 	6
结果:5,4,3,2,1,10,9,8,7,6
*/



4.按照n/2步长,即分为2组。

/*
第二次分组;
5		4
3 		2 		
1		10 	
9		8
7		6
结果:(5,3,1,9,7) (4,2,10,8,6)两组
*/


5.对这两组进行直接插入排序
/*
第二次排序
1		2
3		4
5		6
7		8
9		10
结果:1,2,3,4,5,6,7,8,9,10
*/


6.按照步长n/2, 即1
普通的插入排序,结果就出来了。
因为我这里的数组有点特殊,看不到变化。


四:代码

package test;

import java.util.Arrays;

/**
 * 希尔排序:数组a[n],长度是n+1;
 * 步骤:
 * 1.在直接插入排序的基础上,按照步长对数组元素分组;
 * 2.对同一个分组内的数组进行直接插入排序
 * 3.减小步长,按照步长重新分组,之后再次进行插入排序,直到步长为1
 * 4.最后一次进行直接插入排序,排序工作完成。
 * @author root
 *
 */
public class ShelllSort {
	static void shellSort( int a[] ){
		int n = a.length; 
		int  i , j  ,temp,gap ; //gap 是步长
		// 步长选择n/2递减,直到步长为1;当gap是1时,就是单次的直接插入排序了 
		//最外层循环,简单的说就是按照步长分组的次数
		for(gap = n/2 ;gap >0 ;gap/=2){
			//这层循环其实就是直接插入排序的外层循环;
			//按照步长分为n/2个分组,对这几个分组进行直接插入排序
			for(i=gap;i<n;i++){
				temp=a[i];
				for(j=i-gap;j>=0&&temp<a[j];j-=gap){ //注意:这里的j>=0 ;不然会遗漏a[0];
					a[j+gap] =a[j];
				}
				a[j+gap] = temp;
			}
		}	
	}
	
	public static void main(String[] args) {
		int[]  a ={ 10,9,8,7,6,5,4,3,2,1};
		shellSort(a);
		System.out.println(Arrays.toString(a));
	}
}

运行结果:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


参考:http://blog.youkuaiyun.com/morewindows/article/details/6668714

维基百科:https://zh.wikipedia.org/wiki/%E5%B8%8C%E5%B0%94%E6%8E%92%E5%BA%8F


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值