排序算法之归并排序
归并排序是成功应用分治技术的一个完美例子。
分治法的思想是:(1)将问题的实例划分为同一个问题的几个较小的实例,最好拥有同样的规模;(2)对这些较小的实例求解(一般用递归方法,但在问题规模足够小的时候。有时也会利用另一个算法);(3)如果必要的话,合并这些较小问题的解,以得到原始问题的解。
对于一个需要排序的数组$a[0...n-1],归并排序把它一分为二:$a[0..n/2-1]和$a[n/2...n-1],并对每个子数组递归排序,然后把这两个排好序的子数组合并为一个有序数组。
下面的这个图能够很好地解释归并排序的整个流程
![](http://images0.cnblogs.com/blog/570012/201309/30213151-21898dfedfeb4fdb916e2f1637d83d62.png)
递归的将一个数组分成两部分,直到小的足以解决问题就不再递归(一个数,一定是有序的)。然后再将两个有序的数组合并,最后整个数组就是有序的了。
代码实现:
<?php /** * 归并排序 * 递归调用mergeSort来对数组$a排序 * @param $a 一个可排序的数组 * @return $a 非降序排列的数组 */ function mergeSort(&$a) { $t = count($a); if ($t <= 1) { return; } $b = array_slice($a, 0, intval($t / 2)); //array_slice() 函数在数组中根据条件取出一段值,并返回 ***如果数组有字符串键,所返回的数组将保留键名 $c = array_slice($a, intval($t / 2)); mergeSort($b); mergeSort($c); merge($b, $c, $a); } /** * 将两个有序数组$y, $z合并为一个有序数组$x * @param $y, $z, $x * @return $x */ function merge(&$y, &$z, &$x) { $i = $j = $k = 0; $p = count($y); $q = count($z); while ($i < $p && $j < $q) { if ($y[$i] < $z[$j]) { $x[$k] = $y[$i]; $i++; } else { $x[$k] = $z[$j]; $j++; } $k++; } if ($i == $p) { while ($j < $q) { $x[$k] = $z[$j]; $j++; $k++; } } else { while ($i < $p) { $x[$k] = $y[$i]; $i++; $k++; } } } $arr = array(8, 3, 2, 9, 7, 1, 5); mergeSort($arr); print_r($arr); ?>