前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >排序算法-归并排序

排序算法-归并排序

作者头像
guanguans
发布2018-05-09 10:32:21
7350
发布2018-05-09 10:32:21
举报
文章被收录于专栏:琯琯博客

排序算法-归并排序

代码语言:javascript
复制
<?php
/**
 * 合并两个有序数组为一个有序数组
 *
 * @param  array $value 待排序数组
 *
 * @return array
 */
function merge_array($arr_1, $arr_2) {
    $length_1 = count($arr_1);
    $length_2 = count($arr_2);
    // 归并算法
    // arr_1[$i]和arr_2[$j]比较
    // <= 则 arr_3[$k] = arr_1[$i] 且 ++$i ++$k
    // >= 则 arr_3[$k] = arr_2[$j] 且 ++$j ++$k
    // 直到 $i >= $length_1 或 $j >= $length_2
    //
    // 接着,如果先$i >= $length_1
    // 则, $arr_2[$j~$length_2] 放到 $arr_3后
    // 如果先$j >= $length_2
    // 则, $arr_1[$i~$length_1] 放到 $arr_3后
    $arr_3 = [];
    $i = 0;
    $j = 0;
    $k = 0;
    while ($i < $length_1 && $j < $length_2) {
        if ($arr_1[$i] <= $arr_2[$j]) {
            $arr_3[$k] = $arr_1[$i];
            ++$i;
            ++$k;
            continue;
        }
        $arr_3[$k] = $arr_2[$j];
        ++$j;
        ++$k;
    }
    if ($i === $length_1) {
        for ($s = $j;$s < $length_2;$s++) {
            $arr_3[] = $arr_2[$s];
        }
    }
    if ($j === $length_2) {
        for ($w = $i;$w < $length_1;$w++) {
            $arr_3[$k] = $arr_1[$w];
        }
    }
    return $arr_3;
}
/**
 * 归并排序.
 * 将序列每相邻的两个数字进行归并操作
 *
 * @param  array $value 待排序数组
 *
 * @return array
 */
function merge(&$value = []) {
    $length = count($value);
    if ($length === 1) {
        return;
    }
    $arr = [];
    for ($i = 0;$i < $length;$i++) {
        if ($i % 2 === 0) {
            // 合并每两个元素
            // 判断值类型 integer 直接比大小 合并
            if (is_int($value[$i]) || is_string($value[$i])) {
                if (isset($value[$i + 1])) {
                    if ($value[$i] < $value[$i + 1]) {
                        $arr[floor($i / 2) ][] = $value[$i];
                        $arr[floor($i / 2) ][] = $value[$i + 1];
                        continue;
                    }
                    $arr[floor($i / 2) ][] = $value[$i + 1];
                    $arr[floor($i / 2) ][] = $value[$i];
                    continue;
                }
                $arr[floor($i / 2) ][] = $value[$i];
                continue;
            }
            // 判断值类型 array 遍历元素比大小 合并
            // 把两个有序数组合并成一个有序数组
            // 归并算法详情请看 merge-array
            if (is_array($value[$i])) {
                if (isset($value[$i + 1])) {
                    $length_arr = count($value[$i]);
                    $length_arr_last = count($value[$i + 1]);
                    $arr_tmp = [];
                    $s = 0;
                    $w = 0;
                    $k = 0;
                    while ($s < $length_arr && $w < $length_arr_last) {
                        if ($value[$i][$s] <= $value[$i + 1][$w]) {
                            $arr_tmp[$k] = $value[$i][$s];
                            ++$s;
                            ++$k;
                            continue;
                        }
                        $arr_tmp[$k] = $value[$i + 1][$w];
                        ++$w;
                        ++$k;
                        continue;
                    }
                    if ($s === $length_arr) {
                        for ($j = $w;$j < $length_arr_last;$j++) {
                            $arr_tmp[$k] = $value[$i + 1][$j];
                            ++$k;
                        }
                    }
                    unset($j);
                    if ($w === $length_arr_last) {
                        for ($j = $s;$j < $length_arr;$j++) {
                            $arr_tmp[$k] = $value[$i][$j];
                            ++$k;
                        }
                    }
                    unset($j);
                    $arr[floor($i / 2) ] = $arr_tmp;
                    continue;
                }
                $arr[floor($i / 2) ] = $value[$i];
                continue;
            }
        }
    }
    $value = $arr;
    merge($value);
    return $value[0];
}
/* ----------------- 归并写法二 ------------------ */
$mergeFirst = function ($arr = array()) {
    $len = count($arr);
    $res = [];
    for ($i = 0;$i < $len;$i+= 2) {
        $j = floor($i / 2);
        if (!isset($arr[$i + 1])) {
            $res[$j][] = $arr[$i];
            continue;
        }
        if ($arr[$i] < $arr[$i + 1]) {
            $res[$j][] = $arr[$i];
            $res[$j][] = $arr[$i + 1];
            continue;
        }
        $res[$j][] = $arr[$i + 1];
        $res[$j][] = $arr[$i];
    }
    return $res;
};
$mergeArray = function ($arr1, $arr2) {
    $len1 = count($arr1);
    $len2 = count($arr2);
    $arr3 = [];
    $a = 0;
    $b = 0;
    $k = 0;
    while ($a < $len1 && $b < $len2) {
        if ($arr1[$a] < $arr2[$b]) {
            $arr3[$k] = $arr1[$a];
            $a++;
            $k++;
            continue;
        }
        $arr3[$k] = $arr2[$b];
        $b++;
        $k++;
    }
    if ($a === $len1) {
        for ($i = $b;$i < $len2;$i++) {
            $arr3[] = $arr2[$i];
        }
    }
    unset($i);
    if ($b === $len2) {
        for ($i = $a;$i < $len1;$i++) {
            $arr3[] = $arr1[$i];
        }
    }
    return $arr3;
};
function sorta($arr = array(), $mergeFirst, $mergeArray) {
    if (count($arr) === 1) {
        return $arr[0];
    }
    if (!is_array($arr[0])) {
        $arr = $mergeFirst($arr);
    }
    $len = count($arr);
    $arrNew = [];
    for ($i = 0;$i < $len;$i+= 2) {
        $j = floor($i / 2);
        if (!isset($arr[$i + 1])) {
            $arrNew[$j] = $arr[$i];
            continue;
        }
        $arrNew[$j] = $mergeArray($arr[$i], $arr[$i + 1]);
    }
    $res = sorta($arrNew, $mergeFirst, $mergeArray);
    return $res;
}
/* ----------------- 归并写法 不是用递归 ------------------ */
// 由于归并排序的主要情况是:
// |  5  |  4  |  3  |  2  |  1  |
//       /           \
// | 5 | 4 |        | 3 | 2 | 1 |
//     |                  |
// |5|  |4|          |3|2| |1|
//                     |
//                   |3| |2|
//       --分解完毕--
// |4|  |5|          |3| |2| |1|
//                        |
//                   |1| |2| |3|
//             |
// |  1  |  2  |  3  |  4  |  5  |
//
//其实我是觉得可以不用递归作为分解,所以才写了这个东西
function loopMerge($array) {
    $length = count($array);
    if ($length < 2) {
        return $array;
    }
    // 左边区域的左边界
    $leftMin = 0;
    // 左边区域的右边界
    $leftMax = 0;
    // 右边区域的左边界
    $rightMin = 0;
    // 右边区域的右边界
    $rightMax = 0;
    // 左边区域的移动标
    $l = 0;
    // 右边区域的移动标
    $r = 0;
    // 辅助数组
    $tmp = array_fill(0, $length, 0);
    // 辅助数组的移动标
    $n = 0;
    // 跨度
    $group = 1;
    while ($group < $length) {
        $leftMin = 0;
        while ($leftMin + $group < $length) {
            $leftMax = $leftMin + $group;
            $rightMin = $leftMax;
            if ($rightMin + $group > $length) {
                $rightMax = $length;
            } else {
                $rightMax = $rightMin + $group;
            }
            $l = $leftMin;
            $r = $rightMin;
            $n = $leftMin;
            // 这里是将左边区域的数值跟右边区域的数值进行比较,
            // 并将小的数值放到辅助数组中
            // 直到其中一边的区域的数值全部放到辅助数组中
            while ($l < $leftMax && $r < $rightMax) {
                if ($array[$l] > $array[$r]) {
                    $tmp[$n] = $array[$r];
                    $r++;
                } else {
                    $tmp[$n] = $array[$l];
                    $l++;
                }
                $n++;
            }
            while ($l < $leftMax) {
                $tmp[$n] = $array[$l];
                $l++;
                $n++;
            }
            while ($r < $rightMax) {
                $tmp[$n] = $array[$r];
                $r++;
                $n++;
            }
            for ($n = $leftMin;$n < $rightMax;$n++) {
                $array[$n] = $tmp[$n];
            }
            $leftMin+= $group * 2;
        }
        $group*= 2;
    }
    return $array;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档