經典算法歸併排序的分析及PHP實現

一、原理

把原始數組分成若干子數組,對每一個子數組進行排序,繼續把子數組與子數組合並,合併後仍然有序,直到全部合併完,形成有序的數組

二、基本思想及步驟

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

http://blog.sina.com.cn/s/blog_5ea0192f0100crpb.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章