インプレースソートは基本的に、追加のストレージを使用せずに要素を交換することですよね?
リストに必要なスワップの最小数を見つけるにはどうすればよいですか?
A C D Q R Z E // input
| | | > > > <<< // movement
A C D E Q R Z // output
スワッピング:
A C D Q R Z E
swap Q with E, ACDERZQ
swap R with Q, ACDEQZR
swap R with Z, ACDEQRZ. done.
3スワップ。
アイテムを左または右にシフトすることは基本的に入れ替えですが、アイテムをラインから外して、その場所を別のものに切り替えるための最適な数が必要です。
リストを最終状態がわかっている別の状態に操作する問題を考えてみましょう。
「囲まれたサブグラフ」は、最初のリストの各項目が最後のリストにもある全体の最小のサブセットです。
したがって、初期状態からインデックス4、5、9でサブグラフを作成し、それらの値が10、20、30の場合、それが「囲まれたサブグラフ」になるためには、最後から値を見つけることができるはずです。インデックス4、5、9で状態を示し、それらの値は10、20、30である必要があります(ただし、この順序である必要はありません)。
このことを考慮:
a b c d f e
|
v
b a d f c e
これには明らかに3つのスワップが必要です。 (a <=> b、c <=> d、c <=> f)
上記のアルゴリズムを適用すると、次のようになります。
最小限の数のスワップを実行してソートされた順序にしたい場合は少し難しくなりますが、不可能ではありません。
だから、ソートの順序に到達するために最小限の数のスワップを実行することは不可能ではないことがわかると思いますが、ばかげた数の比較が必要なため、その価値はありません。ヒープソートを使用してください。
単純な選択ソートはどうですか?
あなたの例では:
...グラフなしでとてもシンプル:)
これはどうですか:インデックスiとjで2つの要素を交換するたびに、どこかでタプル(i、j)として記録します。リストがソートされると、抽象的な代数の本を破り、順列、より具体的には転置について読み上げます。順列には正準サイクル分解があり、正準分解を取得したら、そこから転置の最小セットを抽出する方法を考え出すことができます。私は、各サイクルを最小限の数の転置に拡張する貪欲なアルゴリズムを考えています。これを行う方法は1つだけであるはずですが、これが全体として最小限の数の転置を与えるかどうかはわかりません。私の抽象代数は以前ほど良くないので、cs理論スタックでこの質問をすることもできます。
ウィキペディアにリストされているほとんどのアルゴリズムは、使用される定数スペース、最小の反復(比較または実行されるコード)として最適化されています。おそらくスワップ最適化アルゴリズムが存在しますが、私の知識ではありません。
ここで私が頭に浮かぶ簡単な解決策があります。 (最適ではありませんが、十分良い答えです。最適が必要な場合は、ソリューションツリーを列挙する必要がある場合があります)