したがって、Quicksortのスペース効率はO(log(n))です。これは、呼び出しスタックを維持するために必要なスペースです。
Quicksortのウィキペディアページ によれば、これはインプレースアルゴリズムとしての資格があります。これは、アルゴリズムが入力データ構造内の要素を単に交換しているためです。
このページによれば ただし、O(log n)のスペース効率はQuicksortの適格性を失います。スペース効率はO(1)よりも大きいためです。この定義によれば、スペース効率がO(1)より大きいアルゴリズムはインプレースではありません。したがって、これはすべての再帰アルゴリズムが定義上インプレースではないことを意味しますか?
したがって、明らかに、インプレースには2つの異なる定義があります。ウィキペディアは常に完全に信頼できる情報源ではないため、教授の一人に相談しました。
私の教授は2番目の定義に同意しました。彼は、クイックソートはその場にいないと言った。データが入力配列に残っている場合でも、スタックに必要な余分なスペースがそのデータを失格にします。私の教授はアルゴリズムに関する人気のある本を書いたので、彼の意見を大いに尊重しますが、この答えは私には正しくないようです。
インプレースのプロパティは非常に文字通りであると考えています。データはそのまま残ります。元のデータ構造から移動しません。私にとって、この定義はデータのコピーを要求する代わりにポインターを使用してアルゴリズムを実行できることを意味するため、より便利です。これは、アルゴリズムの貴重な特性のようで、「インプレース」という名前に値します。
Intro to Algorithms from MIT押すと、QuickSortがin-placeとして修飾されます-配列内の要素を最大で常に一定量の配列外にある。
結局のところ、人々は常に意見が異なります(トップダウンメモ化は動的プログラミングと見なされますか?一部の「古典的な」人々ではありません)。 MIT Press(私の教授と一緒に、それをインプレースとして認定します)の編集者と著者を信頼しています。
通常、QuickSortの問題は、インプレースでソートされないことではなく、stableではないことです。衛星データは順番に保持されません。
編集
黒井のポイントは、この議論の一部を強調している。私は非常に重要だと思う。
多くの人が、それはO(log(n))再帰呼び出しに余分なメモリを必要とし、データはスタック上のインデックスの形でリークされますが、これは非常に大きなサイズでは無視できますN(log(1,000,000,000)=〜30)。size(data)>> size(index)の場合、通常、ヒープ上のデータの移動に非常に長い時間がかかるという事実を無視します。
データのインデックスは要素自体ではありません-したがって、データの要素は、一定の量(各呼び出しで)を除き、配列の外部に格納されません。
厳密に言えば、Quicksortのスペース効率はO(n)です。退化した場合、配列の各要素のスタックにインデックスが必要になるためです。平均してO(log(n ))。元のデータが元の配列の外部に保存されないことを意味する「インプレース」の縮退した定義を使用しない限り、「インプレース」アルゴリズムと呼ぶ方法はないと思います境界(コピー/スワップ操作を除く)。
この「インプレース」の定義は、任意の「アウトオブプレース」アルゴリズムを使用して、元の配列へのポインターを使用して余分なデータストレージをすべて実行させることにより、この「インプレース」要件を満たすことができるため、縮退します。次に、答えが見つかったら、ポインターデータを使用して元の配列を「インプレース」で並べ替えることができます。
qsortは実際にデータを所定の場所にスワップしますが、再帰に使用されるスタック領域はログにあります2(N)。
これら2つのプロパティは矛盾していません。通常、「インプレース」とは、ヒープメモリ、つまり、アルゴリズムが機能するために明示的に割り当てる必要があるものを指します。
ただし、病的な場合を除き、対数空間の複雑さは基本的に無視できます(たとえば、512バイトのスタックで8ビットのマイクロコントローラーでクイックソートを実行したい場合)。
それはすべて「インプレース」アルゴリズムの定義に依存します。
一定量のメモリを必要とする「インプレース」を定義すると、再帰にlog(N)メモリが必要になるため、クイックソートは「インプレース」ではありません。
「インプレース」をより人間に優しい「入力構造の外部にデータを移動しない」と定義すると、クイックソートは再び「インプレース」ではなくなります。データは、アルゴリズムの動作に必要なクイックソートメソッドが呼び出されるインデックスの形でメモリにリークします。この追加メモリの内容は直接入力に依存しますdepend入力時、どのようにリークしていませんか?
「インプレース」を非コピーとして定義する場合、配列の合計を見つける愚かなアルゴリズムはどうでしょうか。b[i] = a [i + 1のような要素を持つ長さ(n-1)の別の配列を作成します] + a [0]/n。内容は異なりますが、これはちょっとしたコピーですが、この追加メモリの内容は、クイックソートアルゴリズムでスタックに保持されているインデックスのように、入力データの関数です。
ウィキペディアの「インプレース」の定義が最も有用であり、それによると、クイックソートは一定ではない量のメモリを使用するため、「インプレース」ではありません。