Java 详解希尔(Shell)排序

希尔排序(缩小增量法) 属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序。希尔排序并不稳定,O(1)的额外空间,时间复杂度为O(N*(logN)^2)。最坏的情况下的执行效率和在平均情况下的执行效率相比相差不多。

    希尔排序间隔序列函数 h = h * 3+ 1

    希尔排序比插入排序快很多的原因:当h值很大时,数据项每一趟排序移动的元素个数少,但移动的距离很长,这是非常高效的;当h值减小时,每一趟排序移动的元素个数增加,但此时的数据项已经接近于他们最终排序后的位置,插入排序可以更有效


直接附代码

[java]  view plain copy
  1. public class ShellSort {  
  2.     static void sort(int[] array) {  
  3.         int out, in, tmp;  
  4.         int len = array.length;  
  5.         int h = 1;   
  6.         while(h < len / 3// 计算间隔h最大值  
  7.             h = h * 3 + 1;  
  8.           
  9.         while(h > 0){ // 能否继续通过缩小间隔h来分割数据列的判定  
  10.             /* 
  11.              * out为什么从h开始?你分割后的第一子序列应该是这样一个序列,0, h, 2h, 3h, ... 
  12.              * 插入排序的while循环是从1开始的,因为第一个数始终有序,不需要比较,这个需要了解插入排序的算法,所以比较是从第二个数据线,就是数组的第h个下标开始 
  13.              * out的判定为什么是out < len? 
  14.              * 控制数组下标,下面的例子会说道 
  15.              *  
  16.              * 下面举一个例子来解释 
  17.              * 假定有一个10个数据项的数组,数组下标从0 ~ 9 表示 
  18.              * 当h = 4时的子序列情况是这样的,以下标表示 
  19.              * (0 4 8)(1 5 9)(2 6)(3 7) 
  20.              * 我第一次是这么理解的,真对每一组分别进行插入排序(当然也可以这样实现,但是下标不好控制),但是对下面的代码来说这是错误的理解。 
  21.              * 正确的过程是这样的,外层for循环每次对每一分组的前两个数据项进行插入排序,然后前3个,然后前4个 ... 这个和子序列个数有关 
  22.              * 排序过程只真对方括号进行 
  23.              * 当out = 4时进行如下过程 ([0 4] 8) 
  24.              * 当out = 5时([1 5] 9) 
  25.              * 当out = 6时([2 6]) 
  26.              * 当out = 7时([3 7]) 
  27.              * 当out = 8时([0 4 8]) 
  28.              * 当out = 9时([1 5 9]) 
  29.              * h = 4执行完毕,然后h = (h - 1) / 3 = 1开始新的for循环 
  30.              * h = 1时执行过程和h = 4时一样,不过这时的子数列就是原始的数列,蜕变为一个简单的插入排序,这是数组基本有序,数据项移动次数会大大减少 
  31.              *  
  32.              */  
  33.             for(out = h; out < len; out++){ // 外层通过out确定每组插入排序的第二个数据项  
  34.                 // 以下代码就是对子序列进行的插入排序算法  
  35.                 tmp = array[out];  
  36.                 in = out;  
  37.                 /* 
  38.                  * 比较插入排序while循环的写法,这里的while循环与h有关,所以判定就与h有关,包括 in -= h语句 
  39.                  * while(in > 0 && array[in - 1] > tmp){ 
  40.                  * array[in] = array[in - 1]; 
  41.                  * in--; 
  42.                  * } 
  43.                  * array[in] = tmp; 
  44.                  *  
  45.                  */  
  46.                 while(in >= h && array[in - h] >= tmp){  
  47.                     array[in] = array[in - h];  
  48.                     in -= h;  
  49.                 }  
  50.                 array[in] = tmp;  
  51. //              for(int i = 0; i < len; i++)  
  52. //                  System.out.print(array[i] + " ");  
  53. //              System.out.println();  
  54.                                   
  55.             }  
  56.               
  57.             // 缩小间隔  
  58.             h = (h - 1) / 3;  
  59.         }  
  60.     }  
  61. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值