归并排序的原理是把原始数组分成若干子数组(两两分组),对每一个子数组进行排序,继续把子数组与子数组合并(方法:从两子数组头各取一值,小者放入新数组尾部,大者保留至下一趟对比,直至这两个子数组值全部取完),合并后仍然有序,直到全部合并完,形成有序的数组。
算法示意图:
PHP代码实现参考:
/**
* 归并排序
* 原理:把原始数组分成若干子数组(向下递归到2个或1个元素一组),对每一个子数组进行排序,
* 继续把子数组与子数组合并(通过取两数组头),合并后仍然有序,直到全部合并完,形成有序的数组
* @param unknown $arr
* @return unknown
*/
function merge_sort($arr){
// 提取法排序后,合并分组
function do_merge_sort(&$arr,$start,$mid,$end){
if($start==$end)return;
// 新建一个数据用于存放2段数组中提取出来的有序数据
$sorted_arr = [];
// 分别从2段数列中提取首个元素对比
$i = $start;
$j = $mid+1;
while ( $i<=$mid && $j<=$end ) {
if( $arr[$i]<=$arr[$j] ){
$sorted_arr[] = $arr[$i++];
}else{
$sorted_arr[] = $arr[$j++];
}
}
// 将2段数据中剩余的数据添加的有序数列尾部
while ($i<=$mid) $sorted_arr[] = $arr[$i++];
while ($j<=$end) $sorted_arr[] = $arr[$j++];
// 用有序数列替换掉当前段数据
foreach ($sorted_arr as $v){
$arr[$start++] = $v;
}
}
// 拆分分组,再合并
function do_merge_group(&$arr,$start,$end){
$mid = floor( ($start + $end)/2 );
if( $end-$start>1 ){ // 将数列两两拆分
// 递归拆分排序,直到无法再拆分
do_merge_group($arr,$start,$mid);
do_merge_group($arr,$mid+1,$end);
}
// (将拆分到底层的 或 到底层后合并排序过的数据段)合并排序
do_merge_sort($arr,$start,$mid,$end);
}
do_merge_group($arr,0,count($arr)-1);
return $arr;
}
参考:
http://www.cnblogs.com/kkun/archive/2011/11/23/2260271.html
https://www.cnblogs.com/chengxiao/p/6194356.html