涉及的一些知识
-
逆序对
设 A A A为一个有 n n n个数字的有序集( n > 1 n>1 n>1),其中所有数字各不相同。如果存在正整数 i i i、 j j j使得 1 ≤ i < j ≤ n 1 \leq i < j \leq n 1≤i<j≤n而且 A [ i ] > A [ j ] A[i]>A[j] A[i]>A[j],则 ( A [ i ] , A [ j ] ) (A[i],A[j]) (A[i],A[j])这个有序对称为A的一个逆序对。
-
定理1
任意 N N N个不同元素组成的序列平均具有 N ( N − 1 ) / 4 N(N-1)/4 N(N−1)/4个逆序对。
-
定理2
任何仅以交换相邻两元素来排序的算法,其平均时间复杂度为 Ω ( N 2 ) \Omega(N^2) Ω(N2)
由该定理可知,要提高算法效率,我们可以:
- 每次消去不止一个逆序对
- 每次交换相隔较远的两个元素
-
稳定性
能保证两个相等的数,经过排序之后,其在序列的前后位置顺序不变。( A 1 = A 2 A_1=A_2 A1=A2,排序前 A 1 A_1 A1在 A 2 A_2 A2前面,排序后 A 1 A_1 A1还在 A 2 A_2 A2前面)
希尔排序
-
希尔排序(Shell’s Sort)
希尔排序是把元素按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的元素越来越多,当增量减至1时,整个数组恰被分成一组,算法便终止。
-
例:用希尔排序对下面的数组按照从小到大排列
- 对该数组先做5-间隔排序,即把元素按照下标的增量为5的这个规则分组,对每组使用插入排序。
81、35和41一组,对它们使用插入排序
94、17和75一组,对它们使用插入排序
11、95和15一组,对它们使用插入排序
96和28一组,对它们使用插入排序
12和58一组,对它们使用插入排序
- 对进行了5-间隔排序之后的数组再进行3-间隔排序。
- 对进行了3-间隔排序之后的数组再进行1-间隔排序,即直接进行插入排序。
- 对该数组先做5-间隔排序,即把元素按照下标的增量为5的这个规则分组,对每组使用插入排序。
-
主要步骤
- 定义增量序列 D M > D M − 1 > ⋯ > D 1 = 1 D_M>D_{M-1}> \cdots >D_1=1 DM>DM−1>⋯>D1=1
- 对每个 D k D_k Dk进行“ D k D_k Dk-间隔”排序( k = M , M − 1 , ⋯ , 1 k=M,M-1, \cdots ,1 k=M,M−1,⋯,1)
- 注意:“ D k D_k Dk-间隔”有序的序列,在执行“ D k − 1 D_{k-1} Dk−1-间隔”排序后,仍然是“ D k D_k Dk-间隔”有序的。
-
代码实现
-
原始希尔排序
增量序列为: D M = ⌊ S i z e / 2 ⌋ D_M= \lfloor Size/2 \rfloor DM=⌊Size/2⌋, D k = ⌊ D k + 1 / 2 ⌋ D_k= \lfloor D_{k+1}/2 \rfloor Dk=⌊Dk+1/2⌋/* 希尔排序 */ void ShellSort(ListElementType *A, int Size) { int Increment = 0, i = 0, j = 0; ListElementType Temp; for (Increment = Size; Increment > 0; Increment = Increment / 2) /* 增量序列 */ { for (i = Increment; i < Size; i++) /* 插入排序 */ { Temp = A[i]; for (j = i; j >= Increment&&A[j - Increment] > Temp; j = j - Increment) { A[j] = A[j - Increment]; } A[j] = Temp; } } }
原始增量序列下,最坏情况时间复杂度是: T w o r s t ( N ) = Θ ( N 2 ) T_{worst}(N)=\Theta(N^2) Tworst(N)=Θ(N2)
原因:增量元素不互质,则小增量可能根本不起作用。
优化:使用更加高效的增量序列。 -
优化增量序列
- Hibbard增量序列: D k = 2 k − 1 D_k=2^k-1 Dk=2k−1(可以保证相邻元素互质)
- Sedgewick增量序列: { 1 , 5 , 19 , 41 , 109 , ⋯ } \{1,5,19,41,109,\cdots \} {1,5,19,41,109,⋯}( 9 × 4 i − 9 × 2 i + 1 9\times4^i-9\times2^i+1 9×4i−9×2i+1或 4 i − 3 × 2 i + 1 4^i-3\times2^i+1 4i−3×2i+1)
-
-
时间复杂度
-
原始增量序列
最坏情况时间复杂度: T w o r s t ( N ) = Θ ( N 2 ) T_{worst}(N)=\Theta(N^2) Tworst(N)=Θ(N2) -
Hibbard增量序列
最坏情况时间复杂度: T w o r s t ( N ) = Θ ( N 3 / 2 ) T_{worst}(N)=\Theta(N^{3/2}) Tworst(N)=Θ(N3/2)
平均时间复杂度: T a v g ( N ) = O ( N 5 / 4 ) T_{avg}(N)=O(N^{5/4}) Tavg(N)=O(N5/4)(只是猜想,尚未有人能证明) -
Sedgewick增量序列
最坏情况时间复杂度: T w o r s t ( N ) = O ( N 4 / 3 ) T_{worst}(N)=O(N^{4/3}) Tworst(N)=O(N4/3)(只是猜想,尚未有人能证明)
平均时间复杂度: T a v g ( N ) = O ( N 7 / 6 ) T_{avg}(N)=O(N^{7/6}) Tavg(N)=O(N7/6)(只是猜想,尚未有人能证明)
-
-
稳定性
希尔排序是不稳定排序。