希尔排序复杂度详细分析(翻译来源:Hans Werner Lang教授)

来源:H.W. Lang Hochschule Flensburg lang@hs-flensburg.de Impressum Datenschutz © Created: 29.01.1998 Updated: 04.06.2018
(今天我看了一下,发现这个文章的链接已经失效了,因为这个好像是这位教授的上课教案,而不是他的个人博客。我今天点进去发现这个网站是个大学课程地址,然后这篇文章已经没有了。2022.4.13)

希尔排序是最古老的排序算法之一,以其发明者D.L.Shell(1959年)命名[She 59]。虽然该算法速度快,易于理解,易于实现。然而,其复杂性分析却要复杂的多。 (୨୧•͈ᴗ•͈)◞︎♡粉色的字是我写的注释嗷。

算法思想

希尔排序的算法思想如下如下:

  1. 将数据序列存放在二维数组中
  2. 对数组的列进行排序

其结果是对数据进行了部分排序。重复上述过程,但是每次都使用较窄的数组,即列数较少。在最后一步,数组仅有一列。在每一步中,需要进行排序的序列都会增加(列数逐渐变少,每列包含的数组逐渐增多),直到最后一步完全排序为止。但是,由于在前面的步骤中获得的序列已经基本有序,因此在每个步骤中进行的排序操作是有有限。

例如:
3 7 9 0 5 1 6 8 4 2 0 6 1 5 7 3 4 9 8 2 进行排序。
首先,将其排列成具有7列的数组(左),然后对这些列进行排序(右):

3	7	9	0	5	1	6				3	3	2	0	5	1	5
8	4	2	0	6	1	5		→		7	4	4	0	6	1	6
7	3	4	9	8	2	  				8	7	9	9	8	2	

依次排序之后较大的数据元素89已经到了所在列的末尾,但是一个较小的数字(如倒数第二列的2)也在该列末尾。 下一步将该序列分为3列,并再次对其进行排序:

3	3	2				0	0	1
0	5	1				1	2	2
5	7	4				3	3	4
4	0	6		→		4	5	6
1	6	8				5	6	8
7	9	9				7	7	9
8	2					8	9	

现在,序列已经基本有序。在最后一步将其排列成一列时,只需将6、8和9移到正确位置即可。

算法实现

实际上,数据序列不是存储在二维数组中,而是保存在一维数组中。 例如,位置0、5、10、15等处的数据元素想象为具有5列的数组的第一列。通过这种方式建立索引的“列”,对每列进行插入排序。这种方法具有良好的性能。
以下程序从索引位置0n-1对数组a进行排序,数据存放在数组cols中。 因此,在第一步中将数据排列在1391376列中,在最后一步中将数据排列在一列中。 (请注意,如果列数h大于待排序数据元素的总数,则基本上不执行任何操作。也就是说,一开始第一步,数据最大值是多大就给他们分配多少列是没意义的,不进行任何操作)对每列插入排序。

void shellsort (int[] a, int n)
{
    int i, j, k, h, v;
    int[] cols = {1391376, 463792, 198768, 86961, 33936, 13776, 4592,
                    1968, 861, 336, 112, 48, 21, 7, 3, 1}
    for (k=0; k<16; k++)
    {
        h=cols[k];
        for (i=h; i<n; i++)
        {
            v=a[i];
            j=i;
            while (j>=h && a[j-h]>v)
            {
                a[j]=a[j-h];
                j=j-h;
            }
            a[j]=v;
        }
    }
}

算法分析

该算法的正确性在于最后一步(h = 1)中,对整个数组进行普通插入排序。但是由于数据是通过前面的步骤(h = 3、7、21,…)进行预排序,因此最后一步只有很少的插入排序步骤即可。 上面的h序列(在下文中称为h序列)只是一种取增量的方法,实际上希尔排序的性能取决于增量到底怎么取。

背景

寄一封信需要16法郎,一张明信片需要11法郎。但是只能买到3法郎和7法郎的邮票。可以把信和明信片寄出去吗?(兄弟们寄过明信片吗?寄之前邮局已经按照距离规定好了邮费的,寄的时候需要贴上相应价钱的邮票才可以寄出,当没有相应面额的邮票的时候,你就要贴好几枚凑够价钱。比如我们邮政寄一封信1.2元,你可以贴3枚4毛钱的邮票。
显然,问题是将数字 16 和 11 表示为线性组合 k ⋅ 3 + l ⋅ 7 k·3 + l·7 k3+l7,非负整数系数kl。哪些自然数能由3和7的整数倍组合而成的?哪些不能?

定义:设 g , h ∈ I N g,h \in IN g,hIN。如果f可以表示为系数k的线性组合 f = k × g + l × h f=k \times g+l \times h f=k×g+l×h,我们则称fgh的线性组合,系数 k , l ∈ I N 0 k,l \in IN_0 k,lIN0
因为16是3和7的线性组合,即 16 = 3 × 3 + 1 × 7 16=3 \times 3+1 \times 7 16=3×3+1×7,所以可以准确将信封寄出去。

定义:令 g , h ∈ I N g,h \in IN g,hIN互为质数。 用 N ( g , h ) N(g,h) Ngh表示不是gh的组合的所有自然数的(有限)集合,而 γ ( g , h ) γ(g,h) γgh表示这些数中最大的自然数:
N ( g , h ) = { f 元 素 自 然 数   ∣   ¬ ∃ k , l ∈ I N 0 : f = k g + l h } γ ( g , h ) = M a x ( N ( g , h ) ) N(g,h)=\{f元素自然数 |  ¬ \exists k,l \in IN_0:f = kg + lh \} \\ γ(g,h)=Max(N(g,h)) N(gh)={f  ¬klIN0f=kg+lh}γ(gh)=Max(N(gh))

示例:令 g = 3 , h = 7 g = 3,h = 7 g=3h=7
N ( g , h ) = { 1 , 2 , 4 , 5 , 8 , 11 } , γ ( g , h ) = 11 N(g,h) = \{1,2,4,5,8,11 \},γ(g,h) = 11 N(gh)={1,2,4,5,8,11}γ(gh)=11
由于11不是3和7的组合,因此无法寄出明信片。

命题:令 g , h ∈ I N g,h \in IN g,hIN互为质数。 然后 γ ( g , h ) = ( g − 1 ) ⋅ ( h − 1 ) – 1 γ(g, h) = (g-1)·(h-1) – 1 γ(g,h)=(g1)(h1)1
即,每个大于或等于 ( g − 1 ) ⋅ ( h − 1 ) (g-1)·(h-1) (g1)(h1)的数f都是gh的组合。

证明:自己做。

h-排序

定义: h ∈ I N 0 h \in IN_0 hIN0。如果序列 a 1 , . . . , a n a_1,...,a_n a1...an对于所有 i ∈ { 1 , . . . , n − h } i \in \{1,...,n-h \} i{1...nh}都满足 a i ≤ a i + h a_i \leq a_{i+h} aiai+h被称为h-排序(以增量h对数组进行排序
数据存放在具有h列的数组中,然后进行列排序,可以获得h-排序的序列。1个排序的序列被排序。

命题 g , h ∈ I N g,h \in IN g,hIN。一个g-排序的序列在h排序后仍然保持g-排序
证明:详细见参考文献[Knu 73]

定义:经过g-排序h-排序的序列称为g,h-排序

命题:一个g,h排序的序列是g + h-排序的。
证明:对于所有 i ∈ 1 , . . . , n − ( g + h ) i \in{1,...,n-(g + h)} i1...n(g+h),都满足 a i ≤ a i + g + h a_i \leq a_{i+g+h} aiai+g+h,因为 a i ≤ a i + g a_i \leq a_{i + g} aiai+g,序列是按g-排序的;而 a i + g ≤ a i + g + h a_{i + g} \leq a_{i + g + h} ai+gai+g+h序列是h-排序的。因此我们得出以下结论:

命题:如果一个序列是g,h-排序的,那么对于所有 k , l ∈ I N 0 k,l \in IN_0 k,lIN0,它都是kg + lh-排序的,即该序列是以f为增量的有序序列,fg,h的线性组合。
命题:设a为g,h-排序的序列,其中gh是互为质数。 对于所有元素 a i a_i ai a j a_j aj均成立:
j – i ≥ ( g − 1 ) ⋅ ( h − 1 ) ⇒ a i ≤ a j j – i \geq (g-1)·(h-1) \Rightarrow a_i \leq a_j ji(g1)(h1)aiaj,即任意 a i a_i ai的右侧,仅有下 ( g − 1 ) ⋅ ( h − 1 ) – 1 (g-1)·(h-1) – 1 (g1)(h1)1 个元素比它小。
证明:令 j – i = f ≥ ( g − 1 ) ⋅ ( h − 1 ) j – i = f \geq (g-1)·(h-1) ji=f(g1)(h1),则fgh的组合。 因此,该序列是f排序的, a i ≤ a i + f = a j a_i \leq a_{i+f} = a_j aiai+f=aj

命题:设a为g,h-排序的序列,其中gh是互为质数,而d为变量。 如果g和h都在 O ( d ) O(d) O(d)中,则 O ( n ⋅ d ) O(n·d) O(nd)步排序就可以对序列进行d-排序
证明:在 a i a_i ai的右侧最多 ( g − 1 ) ⋅ ( h − 1 ) – 1 (g-1)·(h-1) – 1 (g1)(h1)1 个元素比它小。 对序列进行d-排序意味着将其排列为有d列的二维数组,然后进行列排序。
在一列中 a i a_i ai下的列中,较小元素的每隔d个可能出现一次。 这意味着 a i a_i ai最多只能与 ( ( g − 1 ) ⋅ ( h − 1 ) – 1 ) / d ((g-1)·(h-1) – 1) / d ((g1)(h1)1)/d 个元素交换,或者由于gh O ( d ) O(d) O(d)中,因此必须与 O ( d ) O(d) O(d)个元素交换。
由于这适用于所有 a i ( i = 1 , . . . , n ) a_i(i = 1,...,n) aii=1...n,因此需要进行 O ( n ⋅ d ) O(n·d) O(nd)个排序步骤才能对序列进行d-排序
从这个命题可以得出希尔排序复杂度的上限。

上限

定理1:对于序列h1,3,7,15,31,63,127,...,2k–1,...希尔排序对n个数据排序需要 O ( n ⋅ n ) O(n· \sqrt n) O(nn )个步骤 [ P S 65 ] ^{[PS 65]} [PS65]。(序列h是增量取法
证明:令序列h中, h t h_t ht的值最接 n \sqrt n n 。我们分别对 k ≤ t k \leq t kt k > t k > t k>t两种情况进行分析。

  • k ≤ t k \leq t kt时,因为 h k = 2 k – 1 h_k = 2^k – 1 hk=2k1,因此可知 h k + 1 h_k + 1 hk+1 h k + 2 h_k + 2 hk+2是互为质数,且数量级为 O ( h k ) O(h_k) O(hk)。 因此, O ( n ⋅ h k ) O(n·h_k) O(nhk)步排序足以对数据进行排序。 由于 h k h_k hk是一个几何级数,当 k = 1 , . . . , t k = 1, ..., t k=1,...,t O ( h t ) = O ( n ) O(h_t) = O(\sqrt n) O(ht)=O(n )时候,所有 h k h_k hk的总和为 O ( n ⋅ n ) O(n· \sqrt n) O(nn )。 因此,当 k ≤ t k \leq t kt时,数量级为 O ( n ⋅ n ) O(n· \sqrt n) O(nn )
  • k > t k > t k>t时,当序列放置在包含 h k h_k hk 列的二维数组时,每列中都有 n / h k n/hk n/hk 元素。由于插入排序具有二次复杂性,因此需要 O ( ( n / h k ) 2 ) O((n/h_k)^2) O((n/hk)2) 步对每列进行排序。有 h k h_k hk 列,由于二维数组有 h k h_k hk列,因此对整个数据序列进行 h k h_k hk-排序 需要 O ( ( n / h k ) 2 ⋅ h k ) = O ( n ⋅ n / h k ) O((n/h_k)^2·h_k) = O(n·n/h_k) O((n/hk)2hk)=O(nn/hk) 步。同样, n / h k n/h_k n/hk也是一个几何级数, O ( n / h t ) = O ( n ) O(n/h_t) = O(\sqrt n) O(n/ht)=O(n )。因此,当 k > t k > t k>t时,同样数量级为 O ( n ⋅ n ) O(n· \sqrt n) O(nn )

可以证明,对于这个h序列,上界是比较稳定的。但是还有另外的h序列可以使希尔排序更加高效。

定理2:对于h序列1,2,3,4,6,8,9,12,16,...,2p3q,... ,希尔排序对n个数据排序需要 O ( n ⋅ l o g n 2 ) O(n·logn^2) O(nlogn2)个步骤。 [ P r a 79 ] ^{[Pra 79]} [Pra79]序列h是增量取法
证明:如果 g = 2 g = 2 g=2 h = 3 h = 3 h=3,则 γ ( g , h ) = ( g − 1 ) ⋅ ( h − 1 ) – 1 = 1 γ(g,h)=(g-1)·(h-1)– 1 = 1 γ(gh)=(g1)(h1)1=1,即在一个2,3-排序的序列中,每个元素右侧只有下一个元素可以更小。 O ( n ) O(n) O(n)个步骤足以用插入排序对序列进行排序。分别考虑索引为奇数和偶数的元素,很明显 O ( n ) O(n) O(n)个步骤足以使4,6-排序的序列2-排序。同理 O ( n ) O(n) O(n)个步骤足以使6,9-排序的序列3-排序,以此类推。
上面的h序列具有以下属性:每个 h k h_k hk也会出现 2 h k 2h_k 2hk 3 h k 3h_k 3hk的性质,因此 O ( n ) O(n) O(n)个步骤足以满足每个 h k h_k hkh序列中总共有 l o g n 2 logn^2 logn2个元素;因此,这种h序列的复杂度为 O ( n ⋅ l o g n 2 ) O(n·logn^2) O(nlogn2)
这个h序列在渐近性方面表现最佳,特别是,如果数据序列是基本有序的,则待排序序列中元素较少时该序列效果更好,因为即使只有几个排序步骤,也必须(通过for-i循环)对每个 h k h_k hk数据进行扫描。

通过将这两个定理的结合,可以得到在实际中性能更好的h序列,例如Sedgewick的h序列 [ S e d 96 ] ^{[Sed 96]} [Sed96]。但不幸的是,似乎没有 h 序列能够让希尔排序在最差情况下表现达到 O ( n ⋅ l o g n ) O(n·logn) O(nlogn) [ S e d 96 ] ^{[Sed 96]} [Sed96]。 平均复杂度是否能达到 O ( n ⋅ l o g n ) O(n·logn) O(nlogn)也是一个尚未解决的问题。

排序网络

如果数据的插入排序替换为冒泡排序,则可以将希尔排序实现为排序网络。使用 2p3q 的h 序列时,排序网络由 O ( n ⋅ l o g n 2 ) O(n·logn^2) O(nlogn2)个比较器组成。这与双调排序的比较器个数相同。
下图显示了n=8对应的排序网络。
在这里插入图片描述

模拟

(用于模拟希尔排序的Java小程序)

参考文献

  • Shellsort was originally published by D.L. Shell [She 59].
  • [Knu 73] D.E. Knuth: The Art of Computer Programming, Vol. 3 - Sorting and Searching. Addison-Wesley (1973)
  • [Pra 79] V. Pratt: Shellsort and Sorting Networks. Garland, New York (1979)
  • [PS 65] A. Papernov, G. Stasevic: A Method of Information Sorting in Computer Memories. Problems of Information Transmission 1, 63-75 (1965)
  • [Sed 88] R. Sedgewick: Algorithms. 2nd edition, Addison-Wesley (1988)
  • [Sed 96] R. Sedgewick: Analysis of Shellsort and Related Algorithms. In: Josep Díaz,
  • Maria Serna (Eds.): Algorithms - ESA '96, Fourth Annual European Symposium, Barcelona, Lecture Notes in Computer Science, Vol. 1136, Springer, 1-11 (1996)
  • [She 59] D.L. Shell: A High-Speed Sorting Procedure. Communications of the ACM, 2, 7, 30-32 (1959)

原作者信息

汉斯·沃纳·朗
在这里插入图片描述

  • 1980-1990年 基尔大学基督教-阿尔布雷希特斯大学计算机科学研究所 研究助理
  • 1990-1994年 ISATEC 软硬件有限公司 董事兼总经理
  • 1994-2017年 弗伦斯堡应用科学大学计算机科学教授
  • 2012-2014年 弗伦斯堡应用科学大学信息与通信学院 系主任
  • 2014-2016年 弗伦斯堡应用科学大学信息与通信学院 教务长

碎碎念

昨晚,啊应该是今天凌晨00:00的时候我给教授发了个邮件,想翻译这个文章,咱们凌晨2:30人家就回复我了。
在这里插入图片描述
不论是发邮件的时候还是今天翻译的时候,我深刻感受到了自己是个咸鱼在这里插入图片描述。写完邮件我就想哭,给德国教授写邮件用英语,说不定还有语法错误……然后今天翻译文章时候看到一些名词也是头大。好在我谷歌+必应+百度+查词典最后还是顽强地把它翻译完了。十分欢迎各位大佬批评指正,算了,( ๑ˊ•̥▵•)੭₎₎指正就好了,批评太多我会哭的。
我是安安,萝莉永不服输 (ง •̀o•́)ง。

  • 26
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值