八大排序算法--希尔排序

希尔排序定义

希尔排序其实就是在插入排序的基础上改进而来,不过由于改进的效率特别明显,而且希尔排序本身也算是一个研究的课题了,拥有各种各样的优化方式,各位大牛也写了很多论文来验证希尔排序的不同优化方式, 其中讨论的最多的就是步长

在讲到插入排序时, 我们是比较相邻的两个元素,而希尔排序,是比较相隔n个间距的两个数, n的大小就是步长。

首先看一下代码实现,然后再具体讲解。

代码实现

public static void shellSort(int[] arr) {
	int h = 1;//保证步长大于1
	int len = arr.length;
	while(h < (len/3)) {//保证步长不超过总长度三分之一
		h = h*3 +1;
	}
	
	while(h >= 1) {
		for(int i=h; i<len; i++) {
			int j = i;
			int temp = arr[i];
			for(; j >= h && arr[j - h] > temp; j=j-h) {
				arr[j] = arr[j-h];//将较大数往后移h位
			}
			arr[j] = temp;//将数插入大小合适的位置
		}
		//每进行一次排序后,减少h的大小
		h = (h - 1) / 3;//对应上面的h = h*3 +1;
	}
	System.out.println("shellSort: "+Arrays.toString(arr));
}

可以看到,代码思想基本和插入排序保持一致, 又多了一些东西。首先就是步长,在将插入排序时,我们提到, 如果数据越是趋向于有序,则排序速度回越快。而加入步长以后,可以快速的把大的数往后移动,小的数向前移动,使整体数据越来越趋向于有序, 从而使排序效率得到极大的提升。

如果是完全无序的数列,使用希尔排序的时间复杂度和步长是相关的。在上述代码示例中,我们使用了3h+1这样的增量序列,即{1,3,7,…,3n+1},这个比较常用。除此以外, 还有几种增量序列:

  • {1,2,4,8,…}这种序列并不是很好的增量序列,使用这个增量序列的时间复杂度(最坏情形)是O(n^2)

  • Hibbard提出了另一个增量序列{1,3,7,…,2k-1},这种序列的时间复杂度(最坏情形)为O(n1.5)

  • Sedgewick提出了几种增量序列,其最坏情形运行时间为O(n^1.3),其中最好的一个序列是{1,5,19,41,109,…}

使用增量排序都是根据数据的长度,选取增量序列中可使用的最大的数, 先进行一次大范围的数据移动,使大的数尽可能的往后移动,然后不断的减少步长,直到最后步长为1,进行一次插入排序。

每进行一次希尔排序,整个数据就越有序。

总结

关于希尔排序,先了解这么多,希尔排序的具体使用和具体优化,有很多论文进行阐述和证明,本文只是一个简单的介绍和了解。先了解基本使用再说吧。

附上自动生成测试数组的代码

public static int[] randomArray(int length) {
	int[] arr = new int[length];
	Random random = new Random();
	for(int i=0; i<length; i++) {
		arr[i] = random.nextInt(100);
	}
	//自动生成随机数组,先进行一次原始数据打印
	System.out.println(Arrays.toString(arr));
	return arr;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值