排序算法之 - 归并排序

归并排序也有类似于快速排序的 切割 的过程,但是快速排序会选择基准值,而归并排序则直接将列表 尽可能两等分(若长度为奇数,那么有一侧会少一个元素,左侧还是右侧是无妨的)。当分割到左右两侧都只剩下一个元素的时候,分割完成,开始往上层拼接结果。拼接的大致流程是:取左右两侧队首的元素,比较两者大小,较小的先进入已排序列表。重复执行此流程,直至有一侧为空,将另一侧剩余元素直接合并到已排序列表的右侧。归并排序也是一种“分治法”,将问题分割到不可再分割的最小单元,然后开始往回执行,最终得到结果,它同样要使用递归。。以下是归并排序的执行流程示意图:

  • 归并排序执行流程及结果:
    快速排序执行流程及结果

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
)
复制代码

 

 
posted @   寂地烟火  阅读(38)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示