经典算法归并排序的分析及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

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