一、原理
把原始數組分成若干子數組,對每一個子數組進行排序,繼續把子數組與子數組合並,合併後仍然有序,直到全部合併完,形成有序的數組
二、基本思想及步驟
1.對問題進行分解
2.對分解後的子問題進行處理
3.將處理後的子問題合併成一個大的已經處理的問題即爲待求解
三、舉例
無序數組[6 2 4 1 5 9]先看一下每個步驟下的狀態,完了再看合併細節
第一步 [6 2 4 1 5 9]原始狀態
第二步 [2 6] [1 4] [5 9]兩兩合併排序,排序細節後邊介紹
第三步 [1 2 4 6] [5 9]繼續兩組兩組合並
第四步 [1 2 4 5 6 9]合併完畢,排序完畢
輸出結果[1 2 4 5 6 9]
合併細節
詳細介紹第二步到第三步的過程,其餘類似第二步:[2 6] [1 4] [5 9]
兩兩合併,其實僅合併[2 6] [1 4],所以[5 9]不管它,
原始狀態
第一個數組[2 6]
第二個數組[1 4]
--------------------
第三個數組[...]
第1步,順序從第一,第二個數組裏取出一個數字:2和1
比較大小後將小的放入第三個數組,此時變成下邊這樣
第一個數組[2 6]
第二個數組[4]
--------------------
第三個數組[1]
第2步,繼續剛纔的步驟,順序從第一,第二個數組裏取數據,2和4,
同樣的比較大小後將小的放入第三個數組,此時狀態如下
第一個數組[6]
第二個數組[4]
--------------------
第三個數組[1 2]
第3步,再重複前邊的步驟變成,將較小的4放入第三個數組後變成如下狀態
第一個數組[6]
第二個數組[...]
--------------------
第三個數組[1 2 4]
第4步,最後將6放入,排序完畢第一個數組[...]
第二個數組[...]
--------------------
第三個數組[1 2 4 6]
四、僞代碼
merge(A, p, q, r)
{
n = q - p + 1;
l = r - q;
for i = 1 to n
{
L[i] = A[p+i-1];
}
for j = 1 to l
{
R[j] = A[q+j];
}
L[n+1] = 無窮大;
R[l+1] = 無窮大;
i = 1;
j = 1;
for k = p to r
{
if L[i] <= R[j]
{
A[k] = L[i];
i = i + 1;
}
else
{
A[k] = R[j];
j = j + 1;
}
}
}
merge-sort(A, p, r)
{
if p < r
{
q = 不小於(p + r ) / 2最小整數;
merge-sort(A, p, q);
merge-sort(A, q+1, r);
merge(A, p, q, r);
}
}
五、Merge-Sort的PHP實現
<?php
class MergeSort
{
private $sorted;
public function __construct($_sorted)
{
$this->sorted = $_sorted;
}
public function get()
{
return $this->sorted;
}
//合併方案
public function merge($_start,$_mid,$_end)
{
//將左右兩部分分別合併
$L = array();
$R = array();
for($i=0;$i<=$_mid-$_start-1;$i++)
$L[] = $this->sorted[$_start+$i];
for($i=0;$i<=$_end-$_mid;$i++)
$R[] = $this->sorted[$_mid+$i];
$L[] = 1000000;//無窮大,方便計算
$R[] = 1000000;//無窮大,方便計算
$i = $j = 0;
for($l=$_start;$l<=$_end;$l++)
{
if($L[$i] < $R[$j])
{
$this->sorted[$l] = $L[$i];
$i++;
}
else
{
$this->sorted[$l] = $R[$j];
$j++;
}
}
}
//拆分問題
public function merge_sort($_start,$_end)
{
//獲得問題二分分割點
if($_start < $_end)
{
$mid = ceil(($_start + $_end)/2);
//拆分右半邊
$this->merge_sort($mid,$_end);
//拆分左半邊
$this->merge_sort($_start,$mid-1);
//合併問題
$this->merge($_start,$mid,$_end);
}
}
}
?>
$sorted = array(2,1,4,6,3,7,5,10,28,14,11,11,34,3);
$ms = new MergeSort($sorted);
$ms->merge_sort(0,sizeof($sorted)-1);
六、時間複雜性
歸併排序的遞歸表達式爲:T(n)=2T(n/2)+Θ(c)=θ(nlgn). 其中2表示二分分治後需要處理的策略數。那麼對於K分法同樣可以表達爲(T(n)=KT(n/K)+Θ(c). 大家注意這是K分法的最壞情況,有的時候雖然是K分後,但需要處理的策略並不是等於K,而是小於等於K.比如二分查找的時間遞歸表達式就是T(n)=T(n/2)+Θ(c)=θ(lgn).
參考文獻:
http://www.cnblogs.com/kkun/archive/2011/11/23/merge_sort.html