2013-02-05 6 views
6

私はn-wayマージでいくつかの記事を読むことを試みましたが、その概念を理解していませんでした。私は2-wayマージでn-wayマージを使用する理由について混乱していますか?なぜあなたは彼らがその後、2部の2ウェイマージを行い、その後、これに第3部の2ウェイマージは2部:)なぜn-wayマージを使うべきですか? 2ウェイマージよりもメリットは何ですか?

おかげで、「通常で

答えて

7

をマージソートし、3部の配列を分割するのと同じよう"マージソートでは、配列を2で除算し、深さがlog2nに達するまでマージを開始します。サイズがmの2つの配列の各マージは、2mの操作をとることになります。

これは、(解析タイミングで)、次の式にあなたを取得します。

n/2 * 2 + n/4 * 4 + ... 1 * n = n * log2n

を今、あなたは3ウェイマージを行う場合は、従来の方法との違いは2つあり3で配列を分割します:

  • ここで、分割の深さはlog3nです。
  • マージ中に、2つの要素を比較する代わりに、最低3つの要素を見つける必要があります。三つの要素の最小値を見つけること2つの操作で構成されているので2が乗算され

    n/3 * 2*3 + n/9 * 2*9 + ... 1 * 2*n = 2 * n * log3n

    注こと:

これは、最も基本的な実装では、このような式を得るだろう、ということを意味します。

漸近的には、これら2つはともにΘ(nlogn)です。しかし、おそらく(私は試していない)実際には、その3つの方法のマージソートは、log3nのため、より良いパフォーマンスを与えるだろう。それにもかかわらず、n = 1000000のlog2nはわずか20であり、同じ番号のlog3nは12.5なので、nが非常に大きい場合を除き、この最適化は実際には有効ではないでしょうか。


巧妙な実装では、kウェイマージが実際にマージソートに良い影響を与える可能性があります。最小限のk要素を見つけたら、最小値ではない残りのk-1要素の間の関係を既に知っているということです。だから、それぞれのリストからその最小要素を消費したら、そのリストの新しい値を比較し、残りのk-1要素に関してその順序を見つけることだけが必要です。ヒープを使用すると、これは非常に簡単です。


Jerry's answerも必ず参照してください。私は、マルチウェイマージの真のパワーは、複数のディスクや並列処理を扱うことから来ていると彼に同意します。

+1

私は、並列計算と並列ディスクの読み込みに関して[what jerry says](http://stackoverflow.com/a/14713825/912144)と言いたいと思います。 – Shahbaz

+0

完璧、Shahbaz、それは本当に素晴らしい説明ですありがとう 今私が理解していない部分は、3のグループに分割した後どのようにマージを行いますか?私が3の分を知った後、私は何をしますか? 3要素配列の先頭に置いたとします。次の2要素はどうでしょうか?あなたはサンプルのn単純なコードを教えてもらえますか? 申し訳ありませんが、それは愚かに聞こえるかもしれませんが、それは私が3ウェイマージで把握したことのない部分です。 – ADJ

+1

2つの配列マージで同じことをします。まだマージされていない部分には、各配列のポインタが1つあります(最初は配列の先頭になります)。最小値を見つけたら、それをマージされた配列に入れ、その要素に対応するポインタを前進させます。もう一度同じ問題になります.3つのポインタがあり、最小値を見つけて、それをマージされた配列に追加し、そのポインタを前進させます。繰り返す。 – Shahbaz

10

通常、外部の並べ替えを行うときにマージする複数のストリームになります。たとえば、テラバイトのデータをソートし、64ギガバイトのRAMしか持たないと仮定します。

通常、64ギガバイトで読み込み、ソートして書き出します。 1テラバイト分のデータを繰り返して、一度にメモリに保持できる各 "チャンク"ごとに1つの中間ファイルを作成します。これを改善する方法はありますが、通常は約128ギガバイトのソートされた中間ファイルを作成することが一般的には可能です。そして数はほぼ確実にあなたが定期的にこれを行うためにやっている場合、あなたはおそらく、いくつかを持っている2.

より大きくなります - 一緒にマージする中間ファイルの数であなたを残し

かなりハイエンドのハードウェアでそれを行う。各中間ファイルを別々のディスクドライブに入れて(少なくとも1つ以上を出力する場合)、すべてのデータを一度に2つではなく一度にまとめて、ほぼ確実に速度を向上させることができます。プロセスは一般的にI/O境界になりますので、一度に8個のディスクを読み取る(たとえば)ディスクは、一度に2つのディスクから読み取るのに比べて通常約4倍高速です(ただし、これは真実ではない可能性があります)。より多くの中間ファイルを作成しないようにすると(それ以上のマージが必要になります)、全体的なスピードはおそらくさらに大きな要素によって向上します。

+0

upvoteでしたが、理解しやすいので、shahbazの答えを受け入れました。 – ADJ

関連する問題