一、原理
把原始数组分成若干子数组,对每一个子数组进行排序,继续把子数组与子数组合并,合并后仍然有序,直到全部合并完,形成有序的数组
二、基本思想及步骤
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