排序算法之希尔排序

        希尔排序(Shell's Sort是由 Donald Shell于1959年提出,它的思想的基础是 插入排序。

       在讲解希尔排序之前我们先理解一下什么是逆序对:对于下标i<j ,如果A[i]>A[j] ,则称(i,j)是一对 逆序对(inversion)。

        问题:序列{34, 8, 64, 51, 32, 21}中有多少个逆序对?

        共有 :(34, 8) (34, 32) (34, 21) (64, 51) (64, 32) (64, 21) (51, 32) (51, 21) (32, 21)

        交换2 个相邻元素正好消去1 个逆序对!这是不是很像插入排序?

        插入排序:T(N, I) = O( N+I )      ------->    如果序列 基本有序 ,则插入排序简单且高效。

 

 

    定理:任意N 个不同元素组成的序列平均具有N ( N - 1 ) / 4  个逆序对。

 

    定理:任何仅以交换相邻两元素来排序的算法,其平均时间复杂度为 Ω( N 2 ) 。 

 

    我们能不能每次交换相隔较远的2 个元素?

    要提高算法效率,我们必须每次消去不止1 个逆序对!

 

    要达到预想的结果要先定义一个增量序列,根据增量序列将数据分组,在各组内进行插入排序,然后再取第二个增量,再进行分组排序,直到最后增量等于1,进行直接插入排序。

 

定义增量序列 :

 

 

我们来看看原始的希尔排序的代码实现:

 

原始希尔排序的增量序列定义:

        public static int[] shellSort(int[]arr){
		
		int len = arr.length; //获取数组的长度
		
		for(int d=len/2;d>0;d/=2){ //定义增量序列  **shell排序中最核心
			
			for(int i =d;i<len;i++){  //以下为简单选择排序
				
				for(int j = i;j>0;j--){
					
					if(arr[j]<arr[j-1]){
						
						int temp= arr[j];
						arr[j] = arr[j-1];
						arr[j-1] = temp;
					}
				}
			}
		}
		
		return arr;
	    }
	

在这种增量序列下,在最坏情况 希尔排序的时间复杂度度是O(n2)的,但是上文不是说希尔排序能提高算法的效率吗?

因为问题就出在增量序列的定义上,在下面这种情况下,希尔排序并没有提高效率,最终本质还是一个插入排序:

       

         增量元素不互质,则小增量可能根本不起作用。

        我们思考有没有更好的增量序列定义?

        Hibbard  增量序列   

        Sedgewick 增量序列

        这两个增量序列可以将希尔排序的算法时间复杂度优化到O(n 4/3),关于这两个增量序列在此不再介绍了。

        希尔排序并不是一个稳定的排序算法!相等的元素有可能会被交换!

 

 

参考资料:陈越《数据结构与算法》

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值