10.2.4 希尔排序

算法 10.5
  void ShellInsert ( SqList &L,int dk)
 {
  // 对顺序表L作一趟增量为dk的希尔排序
  for ( i=dk+1; i<=L.length; ++i )
   if ( L.r[i].key < L.r[i-dk].key ) { // 将L.r[i]插入有序子表
    L.r[0] = L.r[i]; L.r[i]=L.r[i-dk];
    for ( j=i-2*dk; j>0 && L.r[0].key < L.r[j].key; j-=dk )
     L.r[j+dk] = L.r[j];       // 记录后移
    L.r[j+dk] = L.r[0];        // 插入到正确位置
   } // if
 } // ShellInsert

算法 10.6
  void ShellSort (SqList &L, int dlta[], int t)
 {
  // 按增量序列 dlta[0..t-1] 对顺序表L作希尔排序
  for (k=0; k<t; ++t)
   ShellInsert(L, dlta[k]); // 一趟增量为 dlta[k] 的插入排序
 } // ShellSort

  希尔排序的时间复杂度和所取增量序列相关,例如已有学者证明,当增量序列为 2t-k-1(k=0,1, …,t-1)时,希尔排序的时间复杂度O (n3/2)
 
 
  将算法 SellInsert 中所有的"dk"改为"1"即为算法 InsertSort,反过来说,算法 ShellInsert 可以看成是 InsertSort 的扩展。

  由于C语言的数组没有"负数"的下标,因此,在dk>1时需对j循环中以防"出界"另作"j>0"的判别,即L.r[0] 不再起到"监视哨"的作用,而仅仅作为一个暂存记录的空间。

  希尔排序的增量序列 dlta[] 可以有多种取法,但必须是,
  (1) dlta[]中各值没有除1之外的公因子;
  (2) dlta[t-1]必须为1。

 例如,dlta[]=……,9,5,3,2,1
   或 dlta[]=……, 31,15,7,3,1
   或 dlta[]=……,40,13,4,1等。