最も効率的な定数空間ソートアルゴリズムは何ですか?


19

私は配列のサイズ以外のバイトを割り当てず、2つの命令に制限されているint配列のソートアルゴリズムを探しています:

  1. SWAP:次のインデックスを現在のインデックスと交換します。

  2. MOVE:カーソルを+1または-1インデックスに移動します。

つまり、indexを交換した100だけでは、隣接していないインデックスを交換したり、インデックスを交換したりすることはできません10。最も効率的なアルゴリズムは何ですか?つまり、総移動量が少ないアルゴリズムですか?


13
奇妙なことではありませんが、巻き上げられたテープに接着されたカートのリストをソートする物理マシンです。マシンはテープを前後にしか移動できず、隣接するカードのみを交換できます。現実の世界ではテレポートできないので、それらは制限です
...-MaiaVictor

2
したがって、配列のサイズ以外のバイトを割り当てないアルゴリズムが必要であると言うとき、要素のストレージのみを参照すると思いますか?私はまだカウンターなどを割り当てることができますか?
ダークホッグ

5
はい。もちろん。いくつかの追加構造を割り当てることができます。配列全体を割り当てて、非常に多くの計算を行うこともできますが、これは0コストとしてカウントされます。最小化する必要があるのは、遅いため、実際の物理マシンのSWAP / MOVEの数だけです。バブルソートは私が思いつくことができる最高のものですが、より良いオプションがあるはずだと思いました。
MaiaVictor

1
私はそのようなアルゴリズムがあるとは思わない。せずに任意の余分なメモリは、任意の制御状態を保存する方法がありませんよ。
ラファエル

1
@svrm:ええ、そして無制限のRAMとテープをRAMにコピーし、無料で任意の計算を行う機能を備えているため、「すべてを試して最適に適用する」アルゴリズムがテープの移動数の点で最適です。実用的ではないかもしれませんが、それは実際にはランタイムが0ではなく数億年であるためです;-)長さNのテープをRAMにコピーするのにNのコストがかかる場合、単純なブルートフォースは最適ではないかもしれませんが、N以内です最適の。しかし、これはあなたの問題に特有のものではありません。この方法で述べられた多くの問題は、偽のアルゴリズムを使用して「オフライン」で解決できます。
スティーブジェソップ

回答:


13

バブルソートの双方向バージョンであるカクテルシェーカーソートを検討してください。低から高にバブルソートし、次に(これが追加される部分です)高から低にバブルソートし、完了するまで繰り返します。これはまだですが、配列の上端近くの小さな要素はNパスではなくシングルパスで最終位置に移動するため、平均で大幅に少ないパスになります。また、スワップが発生した最低位置と最高位置を追跡できます。後続のパスでは、これらのポイントを超えてスキャンする必要はありません。On2


4

配列の順序付けに必要な隣接要素のスワップの数は、配列内の反転の数に等しくなります。Nの合計の要素、最大であり、N *(N-1)/ 2反転、バブルソートこのモデルでスワップの漸近的に最適な数を与えるように。


実際、バブルソートは正確に最適な数のスワップを提供します。ただし、順列ごとに最適な数のスワップを実行する方法がいくつかあり、どれが移動の総数を減らすかは明らかではありません。(バブルソートとは「ソートされていない最大のピックを選択し、ソートの最後に移動する」という意味です)
ピータークラフチュク

4

On2

+

ブールフラグを使用せずに要素を交換したかどうかを知るアルゴリズムを以下に示します(情報をメモリではなく、マシンの状態に保つトリック):

Start:
    Do until we are not at the leftmost position (Op 4)
        move left (Op 2b)

Check:
    If we are at rightmost position (Op 3)
        goto Finished:
    If current value is larger than next value (Op 5)
        goto Unfinished:
    move right (Op 2a)
    Repeat Check:

Unfinished:
    If we are at rightmost position (Op 3)
        goto Start:
    If current value is larger than next value (Op 5)
        swap the elements (Op 1) and move right (Op 2a)
    Repeat Unfinished:

Finished:
    The list is sorted now, output it.

基本的には双方向のバブルソートであるため、GNOMEソートであるEric Lippertのソリューションも機能します。


挿入ソートはどうですか?
ダークホッグ

バブルの並べ替えには、少なくとも2つのループカウンターが必要ですが、これらは既に許可されています。
ラファエル

1
いいえ、カウンターを使用せずに、変更がなくなるまで(最大n回)、左右に移動してから、右から左に移動できます。ブールフラグに変更があるかどうかを記録するための余分なスペースさえ必要ありません。変更がある場合は、別のサブルーチンであることを除いて、同じことを行う別のサブルーチンにジャンプするだけです。
シュリーシュ

1
そしてもちろん、あなたはそれがリストの始まりか終わりであることを知っているかもしれないので、あなたは両端で空白を読むことができると思います。また、スワップする必要があるかどうかを知るために、現在の要素と次の要素の両方を読むと仮定します。
シュリーシュ

1
または、オペレータースワップを「昇順でない場合はスワップ」として変更した場合。
シュリーシュ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.