特别说明:
对于算法,重在理解其思想、解决问题的方法,思路。因此,以下内容全都假定待排序序列的存储结构为:顺序存储结构。
希尔排序算法摘要:
希尔排序又称为“缩小增量排序”。直接插入排序算法在效率上虽说没办法突破 的一个算法。希尔排序算法算是一种属于插入排序类别的方法。
希尔排序算法思想:
算法总体描述:将待排序序列按指定步长,划分成多个子序列,分别对每个子序列应用插入排序进行排序,待全部子序列全部排序完成后,将步长缩小后,再次重新划分子序列并重新排序。如此重复,直至步长降至1为止。
具体描述:
假设待排序序列为 ,则算法可描述如下:
01.step = ;
02.将整个待排序序列划分为以下 个子序列:
{ }、
{ }、
...、
{ };
注意:以上各子序列的最后一个元素的下标均不超过 n。即:
n;
n;
....
n;
03.分别对以上划分好的各子序列进行插入排序;
04.如果 step = 1,则排序完成退出;
05.否则,缩小步长增量 step = ,重新回到 02 点执行;
下面简要分析下,为何希尔排序能成功构造出前文摘要部分所述的条件。首先,将待排序序列按步长划分成多个子序列,则每个子序列的个数就比原子序列少 step 倍,因此,执行插入排序时的效率会比对 n 个数的序列来的高。其次,虽说随着步长 step 的不断缩小,每个子序列的数据量逐渐增大,但每执行完一趟后,待排序序列相比之前一趟都更为有序了一些,此时执行起插入排序,其效率又会有所提高。因此,希尔排序就是如此巧妙地构造出了前文摘要所述的两个条件:少数据量或者待排序序列基本有序。从而提高插入排序的效率,最终提高希尔排序的效率。
希尔排序算法编码参考如下:
1 // 2 // summary : 希尔排序算法.(希尔排序其实算是对直接插入排序算法的改进) 3 // in param : seqlist 待排序列表.同时也是排完序列表. 4 // in param : nLen 列表长度 5 // out param : -- 6 // return : -- 7 // !!!note : 01.以下实现均假设一切输入数据都合法.即:内部不对参数全法性进行校验,默认它们全都合法有效. 8 // 02.排序开始前 seqlist 是无序的,排序结束后 seqlist 是有序的. 9 // 03.该实现版本,步长每次折半. 10 void shell_sort(int seqlist[/*nLen*/], const int nLen) { 11 auto nTemp = 0; 12 auto nStep = nLen >> 1; 13 auto nLoopIdx = 0; // 趟循环 14 auto nOuterIdx = 0; 15 auto nInnerIdx = 0; 16 while (nStep > 0) { 17 for (nLoopIdx = 0; nLoopIdx < nStep; ++nLoopIdx) { 18 for (nOuterIdx = nLoopIdx + nStep; nOuterIdx < nLen; nOuterIdx += nStep) { 19 nTemp = seqlist[nOuterIdx]; 20 for (nInnerIdx = nOuterIdx; nInnerIdx > 0; nInnerIdx -= nStep) { 21 if (seqlist[nInnerIdx] >= seqlist[nInnerIdx - nStep]) { 22 break; 23 } 24 seqlist[nInnerIdx] = seqlist[nInnerIdx - nStep]; 25 } 26 seqlist[nInnerIdx] = nTemp; 27 } 28 } 29 nStep = nStep >> 1; 30 } 31 }