2013-02-05 56 views

回答

7

「正常「合併排序,您將數組除以2,直到達到深度log2n,然後開始合併。兩個大小爲m的數組的每個合併也將執行2m操作。

,它會給你下面的公式(在時序分析):

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

現在,如果你做一個三方合併,你將3分割陣列前面的方法不同的是雙重的:

  • 深度劃分現在是log3n
  • 合併過程中,不是比較2個元素,而是需要找到3個元素的最小值。

這意味着,在最基本的實現,你會得到這樣一個公式:

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

注意2乘以因爲找到最小的三個要素包括2個操作。

漸近地說,這兩個都是Θ(nlogn)。但是,也許(我還沒有嘗試過)在實踐中三路合併排序會因爲其log3n而獲得更好的性能。儘管如此,因爲n = 1000000的log2n僅僅是20,而相同數字的log3n是12.5,我懷疑這種優化是否真的有效,除非n相當大。


通過巧妙的實現,k路合併確實可以對合並排序產生很好的影響。這個想法是,一旦你找到最少的k元素,你就已經知道其他不是最小元素的其他元素之間的關係。因此,一旦從其各自的列表中消耗了該最小元素,您只需比較該列表的新值並查找其相對於其餘k-1元素的排序。使用堆,這將是相當微不足道的。


一定還會看到Jerry's answer。我同意他的看法,多路合併的真正力量來自處理多個磁盤和並行處理。

+1

關於並行計算和並行磁盤讀取,我想說的可能是[什麼傑裏說](http://stackoverflow.com/a/14713825/912144)是它的主要原因。 – Shahbaz

+0

完美,謝謝Shahbaz,那真的是一個很好的解釋 現在我不明白的部分是,在分成3組之後你會怎麼做合併?在我知道3分鐘後,我會做什麼?假設我把它放在3元素數組的開始處,那麼接下來的2個元素呢?你能指點我一個簡單的樣本代碼嗎? 對不起,這可能聽起來很愚蠢,但這是我從來沒有抓住過的3路合併的部分。 – ADJ

+1

與2個數組合並做同樣的事情。您將每個數組的一個指針指向尚未合併的部分(在開始時,它將是數組的開頭)。一旦你找到最小值,你把它放在合併數組中,並推進與該元素相對應的指針。這又是同樣的問題,你有三個指針,找到最小值,將它追加到合併的數組,並提前該指針。重複。 – Shahbaz

10

當您進行外部排序時,您通常會得到多個要合併的流。例如,假設您需要對一個TB數據進行排序,並且只有(比如說)64千兆字節的RAM。

您通常會通過讀取64千兆字節進行排序,然後將其寫出。對全部TB數據重複一次,爲每個可以一次存儲在內存中的「塊」生成一箇中間文件。有許多方法可以改善這一點,但是通常希望的最好方法是生成每個大約128千兆字節的已排序中間文件。

那給你留下了許多中間文件合併到一起 - 和數量將幾乎肯定會大於2

如果你正在做這樣做定期,你可能有一些相當高端的硬件來做到這一點。如果您已將每個中間文件放在單獨的磁盤驅動器上(並且至少還有一個用於輸出),則幾乎可以一次性合併所有數據,而不是一次只合並兩個數據,從而可以提高速度。這個過程通常是I/O綁定的,因此一次讀取8個磁盤的讀取速度通常是從一次只讀取2個磁盤的速度的4倍左右(儘管這取決於您的輸出磁盤具有多少帶寬,這可能並非如此)。通過避免創建更多的中間文件(這將需要進一步合併),您的整體速度可能會提高一個更大的因素。

+0

做了一個upvote,但我接受shahbaz的答案,因爲它更容易理解,謝謝你的幫助:) – ADJ

相關問題