排序算法(二)——希尔排序

排序

希尔排序(shell sort)

主要思想:  先将待排序列分割成若干个子序列,在子序列内分别进行直接插入排序,待整个序列基本有序时,再对全体记录进行直接插入排序。
例如:
* 第一趟 d = 5, 将所有相距为 5 的记录分为一组,从而将整个序列分割成了 5 个子序列。
* 第二趟 d = 2, 将所有相距为 2 的记录分为一组, 从而将整个序列分割成了8 个子序列。(0,2).... (7,9)
* 初始化序列为 [59, 20, 17, 36, 98, 14, 23, 83, 13, 28] 

* a[0]和a[5]比较,59小于14,交换;a[1]和a[7]比较,20小于23,不交换;依次类推,增量为5(前者大于后者则交换)
* 第一趟结果(d=5) [14, 20, 17, 13, 28, 59, 23, 83, 36, 98] 

* a[0]和a[2]比较,14小于17,不交换; a[1]和a[3]比较,20大于13,交换;a[2]和a[4];a[3]和a[5]依次类推,增量为2(前者大于后者则交换)
* 第二趟结果(d=2) [14, 13, 17, 20, 23, 59, 28, 83, 36, 98]

* 第三趟结果(d=1)[13,14,17,20,23,28,36,59,83,98]    —— 当d=1时,内层两个循环相当于就是一个直接插入排序,但是此时序列已经基本有序,却很少进入最内层循环。所以当d=一的时候只是进行比较,很少移动记录,此时这趟复杂度就接近O(N)。

*这样就直到d=1时所有记录进行一次直接插入排序,但是此时效率已经很高,最终所有记录将成为一个有序序列。



	/**
	 * 插入排序: 希尔排序
	 */
	@Override
	public void shellSort(T[] t) {
		int j;
		for (int d = t.length/2; d > 0; d /= 2) {
			for (int i = d; i < t.length; i++) {
				T tmp = t[i];
				for (j = i; j >= d && compare(tmp, t[j - d]); j -= d) {
					t[j] = t[j - d];
				}
				t[j] = tmp;
			}
		}
		System.out.println("希尔排序:");
		print(t);
	}
这里的compare 、 print 方法将在讲解完全部排序介绍,这里仍然才用泛型。
性能分析: 希尔排序的时间性能是一个复杂的问题,因为它所取的增量可能会不同,所以时间复杂度难以确定,但是经过大量试验指出:希尔排序的时间性能在O(N*N)和O(NlogN)z之间,大约为O(N的1.3次方)。
稳定性:若两个记录A和B值相等,但是排序后A、B的先后次序保持不变,则这种排序是稳定的,否则就是不稳定。
总结:
(1)希尔排序是对直接插入排序的一种改进,利用了直接插入排序在记录基本有序时排序效率高的特点。
(2)希尔排序是一种不稳定的排序算法,因为跳跃的可能
(3)将序列分为若干个子序列,开始时增量的取值较大,每个子序列中的记录个数较少,并且提供了跳跃的可能性,排序效率较高,能将后面小的的往前移,前面大的往后移。后来增量逐渐缩小,没个子序列的个数增加,但是此时序列以及基本有序,效率也比较高。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值