归并排序也有类似于快速排序的 切割 的过程,但是快速排序会选择基准值,而归并排序则直接将列表 尽可能两等分(若长度为奇数,那么有一侧会少一个元素,左侧还是右侧是无妨的)。当分割到左右两侧都只剩下一个元素的时候,分割完成,开始往上层拼接结果。拼接的大致流程是:取左右两侧队首的元素,比较两者大小,较小的先进入已排序列表。重复执行此流程,直至有一侧为空,将另一侧剩余元素直接合并到已排序列表的右侧。归并排序也是一种“分治法”,将问题分割到不可再分割的最小单元,然后开始往回执行,最终得到结果,它同样要使用递归。。以下是归并排序的执行流程示意图:
- 归并排序执行流程及结果:
附
PHP实现代码:
<?php
function merge($arrayNeedsSort)
{
if (empty($arrayNeedsSort) || count($arrayNeedsSort) <= 1) {
// 基准条件,退出
return $arrayNeedsSort;
} else {
$res = [];
$left = [];
$right = [];
$length = count($arrayNeedsSort);
if ($length % 2 == 0) {
// 长度为偶数,对半分
list($left, $right) = array_chunk($arrayNeedsSort, ($length / 2));
} else {
// 长度为奇数,左侧比右侧少一
list($left, $right, $last) = array_chunk($arrayNeedsSort, (($length - 1) / 2));
// 切割后将剩余的一个元素补到右侧的列表末尾
$right[] = $last[0];
}
// 先对左侧进行排序
$left = merge($left);
// 再对右侧进行排序
$right = merge($right);
$flag = count($left) + count($right);
while ($flag > 0) {
if (empty($left)) {
// 当左侧为空,直接合并右侧的剩余元素,并退出循环
$res = array_merge($res, $right);
// 为了完整输出中间打印流程,此处将 break; 替换为 $flag = 0;
$flag = 0;
// break;
} elseif (empty($right)) {
// 当右侧为空,直接合并左侧的剩余元素,并退出循环
$res = array_merge($res, $left);
// 为了完整输出中间打印流程,此处将 break; 替换为$flag = 0;
$flag = 0;
// break;
} elseif ($left[0] <= $right[0]) {
$res[] = array_shift($left);
} else {
$res[] = array_shift($right);
}
$flag--;
// 可以打印中间过程进行观察
echo '<pre>';
print_r($res);
}
return $res;
}
}
$array = [5, 9, 3, 1, 2, 8, 4, 7, 6];
$res = merge($array);
echo '<pre>';
print_r($res);
--snip--打印中间值的结果如下--
Array
(
[0] => 5
)
Array
(
[0] => 5
[1] => 9
)
Array
(
[0] => 1
)
Array
(
[0] => 1
[1] => 3
)
Array
(
[0] => 1
)
Array
(
[0] => 1
[1] => 3
)
Array
(
[0] => 1
[1] => 3
[2] => 5
[3] => 9
)
Array
(
[0] => 2
)
Array
(
[0] => 2
[1] => 8
)
Array
(
[0] => 6
)
Array
(
[0] => 6
[1] => 7
)
Array
(
[0] => 4
)
Array
(
[0] => 4
[1] => 6
[2] => 7
)
Array
(
[0] => 2
)
Array
(
[0] => 2
[1] => 4
)
Array
(
[0] => 2
[1] => 4
[2] => 6
)
Array
(
[0] => 2
[1] => 4
[2] => 6
[3] => 7
)
Array
(
[0] => 2
[1] => 4
[2] => 6
[3] => 7
[4] => 8
)
Array
(
[0] => 1
)
Array
(
[0] => 1
[1] => 2
)
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
[8] => 9
)
本文介绍了归并排序的原理,该算法通过切割列表进行尽可能两等分,直到每个子列表只剩一个元素,然后自底向上通过比较和拼接将有序子列表合并,实现整个列表的排序。归并排序是一种基于分治法的排序算法,具有稳定性和较高的效率。文中还附有归并排序的执行流程示意图和实现代码。

1259

被折叠的 条评论
为什么被折叠?



