![]() シェルソートのギャップ23、10、4、1のアクション | |
| クラス | ソートアルゴリズム |
|---|---|
| データ構造 | 配列 |
| 最悪の場合の パフォーマンス | O( n 2 ) (最悪の既知のギャップシーケンス) O( n log 2 n ) (最良の既知の最悪のギャップシーケンス) [1] |
| 最高の パフォーマンス | O( n log n ) (最も多いギャップシーケンス) O( n log 2 n ) (最もよく知られている最悪のギャップシーケンス) [2] |
| 平均的 なパフォーマンス | ギャップシーケンスに依存する |
| 最悪の場合の 空間複雑度 | О( n ) 合計、O(1) 補助 |
| 最適 | いいえ |

シェルソートは、シェルソートまたはシェル法とも呼ばれ、インプレース 比較ソートです。これは、交換によるソート(バブルソート)または挿入によるソート(挿入ソート)の一般化として考えることができます。[3]この方法では、まず互いに離れた要素のペアをソートし、次に比較する要素間のギャップを徐々に減らしていきます。離れた要素から始めることで、単純な最近傍交換よりも速く、一部の位置外れの要素を所定の位置に移動することができます。ドナルド・シェルは、 1959年にこのソートの最初のバージョンを発表しました。[4] [5]シェルソートの実行時間は、使用するギャップシーケンスに大きく依存します。多くの実用的な変種では、その時間計算量を決定することが未解決の問題となっています。
説明
シェルソートは挿入ソートの最適化で、離れた項目の交換を可能にします。アイデアは、どこから始めてもh番目の要素ごとにソートされたリストが生成されるように要素のリストを整理することです。このようなリストはhソートされていると言われます。また、それぞれが個別にソートされたh個のインターリーブ リストと考えることもできます。[6] hの値を大きくして開始すると、元のリスト内で要素が長距離を移動できるため、大量の無秩序がすぐに軽減され、より小さなhソート ステップで行う作業が少なくなります。[7]次に、リストを小さな整数kでk ソートすると、リストはhソートされたままになります。 h = 1での最終ソートにより、 最後にリストが完全にソートされることが保証されますが、[6] h値の減少シーケンスを慎重に選択すると、この最終パスで行う作業がほとんど残りません。
簡単に言えば、1024 個の数字の配列がある場合、最初のギャップ ( h ) は 512 になる可能性があるということです。次に、リスト全体にわたって、前半の各要素を後半の要素と比較します。2 番目のギャップ ( k ) は 256 で、配列は 4 つのセクション (0、256、512、768 から始まる) に分割され、各セクションの最初の項目が互いに相対的に並べ替えられていることを確認し、次に各セクションの 2 番目の項目を並べ替える、というように続きます。実際には、ギャップのシーケンスは任意にすることができますが、最後のギャップは常に 1 で並べ替えが完了します (実質的に通常の挿入並べ替えで終了します)。
ギャップ 5、3、1 での Shellsort の実行例を以下に示します。
最初のパスである 5 ソートでは、5 つの個別のサブ配列 ( a 1、a 6、a 11 )、 ( a 2、a 7、a 12 )、 ( a 3、a 8 )、 ( a 4、a 9 )、 ( a 5、a 10 ) に対して挿入ソートを実行します。たとえば、サブ配列 ( a 1、a 6、a 11 ) は (62、 17、 25) から (17、 25、 62) に変更されます。次のパスである 3 ソートでは、3 つのサブ配列 ( a 1、a 4、a 7、a 10 )、 ( a 2、a 5、a 8、a 11 )、 ( a 3、a 6、a 9、a 12 ) に対して挿入ソートを実行します。最後のパスである 1 ソートは、配列全体 ( a 1、...、a 12 ) の通常の挿入ソートです。
例が示すように、Shellsort が操作するサブ配列は最初は短く、後で長くなりますが、ほぼ順序付けられます。どちらの場合も、挿入ソートは効率的に機能します。
挿入ソートとは異なり、シェルソートは安定したソートではありません。ギャップのある挿入によって等しい要素が互いに通過し、元の順序が失われるためです。これは、入力が部分的にソートされている場合に実行速度が速くなるという点で、 適応ソート アルゴリズムです。
擬似コード
内部挿入ソートを使用した Marcin Ciura のギャップシーケンスを使用します。
# 配列 a[0...n-1] をソートします。
gaps = [ 701 , 301 , 132 , 57 , 23 , 10 , 4 , 1 ] # Ciuraギャップシーケンス
# 最大のギャップから始めて、ギャップ 1 まで処理します
# 挿入ソートに似ていますが、各ステップで 1 ではなくギャップが使用されます
foreach ( gap in gaps ) { # gaps 内のすべての要素に対してギャップ付き挿入ソートを実行します# 各ループでは a[0..gap-1] がギャップ順になりますfor ( i = gap ; i < n ; i += 1 ) { # a[i] を temp に保存し、位置 i に穴を開けますtemp = a [ i ] # a[i] の正しい位置が見つかるまで、以前にギャップソートされた要素を上にシフトしますfor ( j = i ; ( j >= gap ) && ( a [ j - gap ] > temp ); j -= gap ) { a [ j ] = a [ j - gap ] } # temp (元の a[i]) を正しい位置に配置しますa [ j ] = temp } }
ギャップシーケンス
どのギャップ シーケンスを使用するかを決定するのは困難です。1 を含むすべてのギャップ シーケンスは正しいソートを生成します (これにより、最終パスが通常の挿入ソートになります)。ただし、このようにして得られた Shellsort のバージョンの特性は大きく異なる場合があります。ギャップが少なすぎるとパスが遅くなり、ギャップが多すぎるとオーバーヘッドが発生します。
以下の表は、これまでに公開されたほとんどの提案されたギャップシーケンスを比較したものです。これらの中には、ソートされた配列のサイズ ( N ) に応じて減少する要素を持つものがあります。その他は増加する無限シーケンスで、 N未満の要素は逆の順序で使用する必要があります。
Nのバイナリ表現に連続するゼロが多数含まれる場合、Shell のオリジナルのギャップ シーケンスを使用する Shellsort では、最悪の場合、Θ( N 2 ) 回の比較が行われます。たとえば、Nが 2 の累乗に等しい場合、中央値より大きい要素と小さい要素がそれぞれ奇数位置と偶数位置を占めるときに、最後のパスでのみ比較されるため、このケースが発生します。
比較ソートに最適なO ( N log N )よりも複雑度は高くなりますが、 Pratt のバージョンはソート ネットワークに適しており、 Batcher のビトニック ソーターと同じ漸近ゲート複雑度を持ちます。
Gonnet と Baeza-Yates は、連続するギャップの比率がおよそ 2.2 に等しいときに、Shellsort が平均して比較回数が最も少なくなることを観察しました。[13]これが、比率 2.2 のシーケンスと比率 2.25 の Tokuda のシーケンスが効率的である理由です。ただし、なぜそうなるのかはわかっていません。Sedgewick は、最大公約数が低いギャップ、または互いに素なギャップを使用することを推奨しています。[18] [検証失敗]奇数のギャップは実際にはうまく機能しているようです。偶数のギャップを避けることで 25% の削減が観測されています。3 と 5 の倍数のギャップを避けると、10% 未満の小さな利点が得られるようです。[独自の研究? ]
平均比較回数に関しては、Ciuraのシーケンス[15]が最も優れた性能を持っていることが知られています。701を超えるギャップは決定されませんでしたが、シーケンスは再帰式に従ってさらに拡張できます。
単純な式 (ここで、 )で定義される徳田数列は、実際の用途に推奨できます。
最大入力サイズが小さい場合(シェルソートをクイックソートやマージソートなどの他の再帰ソートアルゴリズムによって小さなサブ配列に使用する場合に発生する可能性がある)、各入力サイズに対して最適なシーケンスを作成することができます。[19] [20]
計算の複雑さ
次の特性が成り立ちます。任意のh 1ソート済み配列をh 2ソートした後、配列はh 1ソートされたままです。[21]すべてのh 1ソート済みおよびh 2ソート済み配列は、任意の非負整数a 1およびa 2に対して、( a 1 h 1 + a 2 h 2 ) ソート済みでもあります。したがって、シェルソートの最悪ケースの複雑性はフロベニウス問題に関連しています。gcd = 1の整数h 1、...、h nが与えられた場合、フロベニウス数g ( h 1、...、h n ) は、非負整数a 1、...、a nでa 1 h 1 + ... + a n h nとして表すことができない最大の整数です。フロベニウス数の既知の公式を使用して、いくつかのクラスのギャップシーケンスについてシェルソートの最悪ケースの複雑性を決定できます。[22]証明された結果は上記の表に示されています。
マーク・アレン・ワイスは、入力配列が逆順の場合、シェルソートはO(NlogN )時間で実行されることを証明した。 [23]
平均演算回数に関しては、実証された結果のいずれも実際のギャップシーケンスには関係ありません。2の累乗であるギャップについては、Espelidはこの平均を と計算しました。[24] Knuthは、 2つのギャップ( h、1)を持つN要素配列のソートの平均複雑度を と決定しました。[3]したがって、h = Θ( N 1/3 )の2パスシェルソートは、平均してO ( N 5/3 )の比較/反転/実行時間になります。Yaoは、3パスシェルソートの平均複雑度を見つけました。[25]彼の結果はJansonとKnuthによって改良されました: [26] 3つのギャップ( ch、cg、1)を持つシェルソート中の平均比較/反転/実行時間( hとgは互いに素)は、最後の式のψ ( h , g )は、漸近的に等しい複雑な関数です。特に、h = Θ( N7 /15 )かつg = Θ( N1 /5 )のとき、ソートの平均時間はO ( N23 /15 )です。
実験に基づいて、ヒバードのギャップシーケンスを使用したシェルソートは平均O ( N 5/4 ) 時間で実行され、[3]ゴネットとバエザ・イェーツのシーケンスでは平均 0.41 N ln N (ln ln N + 1/6) の要素移動が必要であると推測されています。[13]ソートされた配列に数百万の要素が含まれている場合、以前に他のシーケンスに対して提案された平均操作数の近似値は失敗します。
下のグラフは、さまざまなギャップシーケンスで使用される要素比較の平均数を理論上の下限値、つまり log 2 Nで割った値を示しています。Ciuria のシーケンス 1、4、10、23、57、132、301、701 (Ci01 と表示) は、式 に従って拡張されています。
.svg/500px-Shell_sort_average_number_of_comparisons_(English).svg.png)
コルモゴロフ複雑度の理論を適用して、Jiang、Li、およびVitányi [27] は、pパス Shellsortでの平均操作数/実行時間の順序の下限を次のように証明しました。 p ≤ log 2 Nの場合、Ω( pN 1+1/ p ) 、 p > log 2 Nの場合、Ω( pN )です。したがって、Shellsort は、ギャップ数が配列サイズの対数に比例して増加するギャップシーケンスを使用する場合にのみ、N log Nのように漸近的に増加する平均時間で実行できる見込みがあります。ただし、 Shellsort が、比較ソートに最適な平均ケース複雑度のこの漸近順序に到達できるかどうかは不明です。下限 は、まで のパス数ごとにVitányi [28]によって改善されました。実際、平均ケースで現在知られているすべての境界(下限と上限)は、この下限と正確に一致しています。たとえば、Janson-Knuth の上限は、使用された増分シーケンスの結果の下限と一致するという新しい結果が得られ、この増分シーケンスの 3 パス シェルソートでは比較/反転/実行時間が使用されていることがわかります。この式を使用すると、下限が不明な増分シーケンスを検索できます。たとえば、4 パスの増分シーケンスでは、 増分シーケンスの 下限が より大きい場合です。下限は次のようになります。
シェルソートのどのバージョンでも、最悪の場合の複雑度はより高次のものである。プラクストン、プーネン、スールは、それが少なくとも と同じ速さで増加することを示した。[29] [30]ロバート・サイファーは、すべての に対してとなる より強い下限を証明した。[31]
アプリケーション
Shellsortはクイックソートよりも多くの操作を実行し、キャッシュミス率も高い。しかし、少ないコードで実装でき、コールスタックも使用しないため、組み込みシステム向けのC標準ライブラリのqsort関数の実装では、クイックソートの代わりにShellsortを使用している。たとえば、uClibcライブラリではShellsortが使用されている。[32]同様の理由で、過去にはLinuxカーネルでもShellsortが使用されていた。[33]
Shellsortは、短いサブ配列をソートしたり、再帰の深さが指定された制限を超えたときに速度低下を防ぐための、イントロスペクティブソートのサブアルゴリズムとしても機能します。この原理は、たとえばbzip2コンプレッサで採用されています。[34]
参照
参考文献
- ^ abc Pratt, Vaughan Ronald (1979). Shellsort and Sorting Networks (Outstanding Dissertations in the Computer Sciences) (PDF) . Garland. ISBN 978-0-8240-4406-02021年9月7日時点のオリジナルよりアーカイブ(PDF) 。
- ^ “Shellsort & Comparisons”. 2019年12月20日時点のオリジナルよりアーカイブ。 2015年11月14日閲覧。
- ^ abcde Knuth, Donald E. (1997). 「Shell の方法」.コンピュータプログラミングの芸術. 第 3 巻: ソートと検索(第 2 版). マサチューセッツ州レディング: Addison-Wesley. pp. 83–95. ISBN 978-0-201-89685-5。
- ^ ab Shell, DL (1959). 「高速ソート手順」(PDF) . Communications of the ACM . 2 (7): 30–32. doi :10.1145/368370.368387. S2CID 28572656. 2017年8月30日時点 のオリジナル(PDF)からアーカイブ。 2011年10月18日閲覧。
- ^ 古い教科書や参考文献の中には、マーリーン・メッツナー・ノートンにちなんでこれを「シェル・メッツナー」ソートと呼ぶものがあるが、メッツナーによれば、「私はこのソートとは何の関係もなく、私の名前がそれに付けられるべきではなかった」とのことである。「シェルソート」を参照。米国国立標準技術研究所。2007年7月17日閲覧。
- ^ abc セジウィック、ロバート(1998)。Cアルゴリズム。第 1 巻 (第 3 版)。アディソン・ウェズレー。pp. 273–281。ISBN 978-0-201-31452-6。
- ^ カーニハン、ブライアン W. ;リッチー、デニス M. (1996)。プログラミング言語 C (第 2 版)。プレンティス ホール。p. 62。ISBN 978-7-302-02412-5。
- ^ Frank, RM; Lazarus, RB (1960). 「高速ソート手順」Communications of the ACM . 3 (1): 20–22. doi : 10.1145/366947.366957 . S2CID 34066017.
- ^ Hibbard, Thomas N. (1963). 「最小記憶ソートの実証的研究」Communications of the ACM . 6 (5): 206–213. doi : 10.1145/366552.366557 . S2CID 12146844.
- ^ Papernov, AA; Stasevich, GV (1965). 「コンピュータメモリ内の情報ソートの方法」(PDF) .情報伝送の問題. 1 (3): 63–75.
- ^ Incerpi, Janet; Sedgewick, Robert (1985). 「Shellsort の改良された上限」(PDF) . Journal of Computer and System Sciences . 31 (2): 210–224. doi :10.1016/0022-0000(85)90042-x.
- ^ Sedgewick, Robert (1986). 「シェルソートの新しい上限」. Journal of Algorithms . 7 (2): 159–173. doi :10.1016/0196-6774(86)90001-5.
- ^ abc Gonnet, Gaston H.; Baeza-Yates, Ricardo (1991). 「Shellsort」.アルゴリズムとデータ構造ハンドブック: Pascal と C で(第 2 版). マサチューセッツ州レディング: Addison-Wesley. pp. 161–163. ISBN 978-0-201-41607-7広範囲にわたる実験により、
α
= 0.45454 < 5/11
で定義されたシーケンスは、他のシーケンスよりも大幅に優れたパフォーマンスを発揮することが示されています。⌊ 0.45454 n ⌋を計算する最も簡単な方法は、整数演算を使用することです。
(5 * n — 1)/11 - ^ 徳田尚之 (1992)。「改良されたシェルソート」。van Leeuven, Jan (編)。アルゴリズム、ソフトウェア、アーキテクチャに関する IFIP 第 12 回世界コンピュータ会議議事録。アムステルダム: North-Holland Publishing Co. pp. 449–457。ISBN 978-0-444-89747-3。
- ^ ab Ciura, Marcin (2001). 「Shellsort の平均ケースに最適な増分」(PDF)。 Freiwalds, Rusins (編)。Proceedings of the 13th International Symposium on Fundamentals of Computation Theory。 ロンドン: Springer-Verlag。 pp. 106–117。ISBN 978-3-540-42487-12018年9月23日時点のオリジナル(PDF)よりアーカイブ。
- ^ Lee, Ying Wai (2021年12月21日). 「Shellsortにおける経験的に改良されたTokudaギャップシーケンス」. arXiv : 2112.11112 [cs.DS].
- ^ Skean, Oscar; Ehrenborg, Richard; Jaromczyk, Jerzy W. (2023年1月1日). 「Shellsortの最適化の観点」. arXiv : 2301.00316 [cs.DS].
- ^ Sedgewick, Robert (1998)。「Shellsort」。C ++ アルゴリズム、パート 1 ~ 4: 基礎、データ構造、ソート、検索。マサチューセッツ州レディング: Addison-Wesley。pp. 285 ~292。ISBN 978-0-201-35088-3。
- ^ Forshell, Olof (2018 年 5 月 22 日)。「シェルソートのサブシーケンスの長さを選択する方法」。Stack Overflow。 シェルソートのための最速ギャップシーケンス? (2018 年 5 月 23 日) での追加解説。
- ^ Lee, Ying Wai (2021年12月21日). 「 n≤16要素のシェルソートにおける最適なギャップシーケンス」. arXiv : 2112.11127 [ math.CO ].
- ^ Gale, David ; Karp, Richard M. (1972 年 4 月). 「ソート理論における現象」(PDF) . Journal of Computer and System Sciences . 6 (2): 103–115. doi : 10.1016/S0022-0000(72)80016-3 .
- ^ Selmer, Ernst S. (1989 年 3 月). 「シェルソートとフロベニウス問題について」(PDF) . BIT 数値数学. 29 (1): 37–40. doi :10.1007/BF01932703. hdl : 1956/19572 . S2CID 32467267.
- ^ ワイス、マーク・アレン(1989年)。「シェルソートの良い事例」。Congressus Numerantium。73 : 59-62 。
- ^ Espelid, Terje O. (1973 年 12 月). 「シェルソートアルゴリズムの分析」. BIT 数値数学. 13 (4): 394–400. doi :10.1007/BF01933401. S2CID 119443598. 引用された結果は399ページの式(8)である。
- ^ Yao, Andrew Chi-Chih (1980). 「(h, k, 1)-Shellsort の分析」(PDF) . Journal of Algorithms . 1 (1): 14–50. doi :10.1016/0196-6774(80)90003-6. S2CID 3054966. STAN-CS-79-726. 2019年3月4日時点の オリジナル( PDF)よりアーカイブ。
- ^ Janson, Svante ; Knuth, Donald E. (1997). 「3 つの増分によるシェルソート」(PDF) .ランダム構造とアルゴリズム. 10 (1–2): 125–142. arXiv : cs/9608105 . CiteSeerX 10.1.1.54.9911 . doi :10.1002/(SICI)1098-2418(199701/03)10:1/2<125::AID-RSA6>3.0.CO;2-X.
- ^ Jiang, Tao; Li, Ming ; Vitányi, Paul (2000 年 9 月). 「Shellsort の平均ケース複雑度の下限」(PDF) . Journal of the ACM . 47 (5): 905–911. arXiv : cs/9906008 . CiteSeerX 10.1.1.6.6508 . doi :10.1145/355483.355488. S2CID 3265123.
- ^ Vitányi, Paul (2018 年 3 月). 「Shellsort の平均ケースの複雑さについて」(PDF) .ランダム構造とアルゴリズム. 52 (2): 354–363. arXiv : 1501.06461 . doi :10.1002/rsa.20737. S2CID 6833808.
- ^ Plaxton, C. Greg; Poonen, Bjorn ; Suel, Torsten (1992 年 10 月 24 ~ 27 日)。「Shellsort の下限値の改良」(PDF) 。議事録、第 33 回コンピュータ サイエンスの基礎に関する年次シンポジウム。第 33 巻。ピッツバーグ、米国。pp. 226 ~ 235。CiteSeerX 10.1.1.43.1393。doi : 10.1109 / SFCS.1992.267769。ISBN 978-0-8186-2900-6. S2CID 15095863。
{{cite book}}: CS1 maint: location missing publisher (link) - ^ Plaxton, C. Greg; Suel, Torsten (1997 年 5 月). 「Shellsort の下限値」(PDF) . Journal of Algorithms . 23 (2): 221–240. CiteSeerX 10.1.1.460.2429 . doi :10.1006/jagm.1996.0825.
- ^ Cypher, Robert (1993). 「シェルソートソーティングネットワークのサイズの下限値」SIAM Journal on Computing 22 : 62–71. doi :10.1137/0222006.
- ^ Novoa, Manuel III. 「libc/stdlib/stdlib.c」 。 2014年10月29日閲覧。
- ^ "kernel/groups.c". GitHub . 2012年5月5日閲覧。
- ^ Julian Seward. 「bzip2/blocksort.c」 。 2011年3月30日閲覧。
文献
- Knuth, Donald E. (1997)。「シェル法」。コンピュータプログラミングの技法。第 3 巻: ソートと検索(第 2 版)。マサチューセッツ州レディング: Addison-Wesley。pp. 83–95。ISBN 978-0-201-89685-5。
- Shellsort および関連アルゴリズムの分析、Robert Sedgewick、第 4 回ヨーロッパアルゴリズムシンポジウム、バルセロナ、1996 年 9 月。
外部リンク
- アニメーションソートアルゴリズム: Wayback Machineの Shell Sort (2015 年 3 月 10 日アーカイブ) – グラフィカルなデモンストレーション
- ハンガリーの民族舞踊である、5、3、1の隙間があるシェルソート

