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等。 |