PHP排序算法之归并排序(Merging Sort)实例详解


Posted in PHP onApril 21, 2018

本文实例讲述了PHP排序算法之归并排序(Merging Sort)。分享给大家供大家参考,具体如下:

基本思想:

归并排序:就是利用归并(合并)的思想实现的排序方法。它的原理是假设初始序列含有 n 个元素,则可以看成是 n 个有序的子序列,每个子序列的长度为 1,然后两两归并,得到 ⌈ n / 2⌉ (⌈ x ⌉ 表示不小于 x 的最小整数)个长度为 2 或 1 的有序序列;再两两归并,······,如此重复,直至得到一个长度为 n 的有序序列为止,这种排序方法就成为 2 路归并排序。

一、归并的过程:

a[i] 取 a 数组的前部分(已经排好序),a[j] 取 a 数组的后部分(已经排好序)

r 数组存储排好序的 a 数组

比较 a[i]和 a[j] 的大小,若 a[i] ≤ a[j],则将第一个有序表中的元素 a[i] 复制到 r[k] 中,并令 i 和 k 分别加上 1;否则将第二个有序表中的元素 a[j] 复制到 r[k] 中,并令 j 和 k 分别加上 1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到 r 中从下标 k 到下标 t 的单元。归并排序的算法我们通常用递归实现,先把待排序区间 [s,t] 以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间 [s,t]。

二、归并操作:

归并操作(merge),也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法。

如 设有数列{6,202,100,301,38,8,1}

初始状态:6 , 202 , 100 , 301 , 38 , 8,1

第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;

第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;

第三次归并后:{1,6,8,38,100,202,301},比较次数:4;

总的比较次数为:3+4+4=11,;

逆序数为14;

三、算法描述:

归并操作的工作原理如下:

第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置

第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

重复步骤3直到某一指针超出序列尾

将另一序列剩下的所有元素直接复制到合并序列尾

PHP排序算法之归并排序(Merging Sort)实例详解

算法实现:

我们先来看看主函数部分:

//交换函数
function swap(array &$arr,$a,$b){
  $temp = $arr[$a];
  $arr[$a] = $arr[$b];
  $arr[$b] = $temp;
}
//归并算法总函数
function MergeSort(array &$arr){
  $start = 0;
  $end = count($arr) - 1;
  MSort($arr,$start,$end);
}

在总函数中,我们只调用了一个 MSort() 函数,因为我们要使用递归调用,所以将 MSort() 封装起来。

下面我们来看看 MSort() 函数:

function MSort(array &$arr,$start,$end){
  //当子序列长度为1时,$start == $end,不用再分组
  if($start < $end){
    $mid = floor(($start + $end) / 2); //将 $arr 平分为 $arr[$start - $mid] 和 $arr[$mid+1 - $end]
    MSort($arr,$start,$mid);  //将 $arr[$start - $mid] 归并为有序的$arr[$start - $mid]
    MSort($arr,$mid + 1,$end);  //将 $arr[$mid+1 - $end] 归并为有序的 $arr[$mid+1 - $end]
    Merge($arr,$start,$mid,$end);    //将$arr[$start - $mid]部分和$arr[$mid+1 - $end]部分合并起来成为有序的$arr[$start - $end]
  }
}

上面的 MSort() 函数实现将数组分半再分半(直到子序列长度为1),然后将子序列合并起来。

现在是我们的归并操作函数 Merge() :

//归并操作
function Merge(array &$arr,$start,$mid,$end){
  $i = $start;
  $j=$mid + 1;
  $k = $start;
  $temparr = array();
  while($i!=$mid+1 && $j!=$end+1)
  {
    if($arr[$i] >= $arr[$j]){
      $temparr[$k++] = $arr[$j++];
    }
    else{
      $temparr[$k++] = $arr[$i++];
    }
  }
  //将第一个子序列的剩余部分添加到已经排好序的 $temparr 数组中
  while($i != $mid+1){
    $temparr[$k++] = $arr[$i++];
  }
  //将第二个子序列的剩余部分添加到已经排好序的 $temparr 数组中
  while($j != $end+1){
    $temparr[$k++] = $arr[$j++];
  }
  for($i=$start; $i<=$end; $i++){
    $arr[$i] = $temparr[$i];
  }
}

到了这里,我们的归并算法就完了。我们调用试试:

$arr = array(9,1,5,8,3,7,4,6,2);
MergeSort($arr);
var_dump($arr);

运行结果:

array(9) {
 [0]=>
 int(1)
 [1]=>
 int(2)
 [2]=>
 int(3)
 [3]=>
 int(4)
 [4]=>
 int(5)
 [5]=>
 int(6)
 [6]=>
 int(7)
 [7]=>
 int(8)
 [8]=>
 int(9)
}

复杂度分析:

由于归并算法无论原来的序列是否有序都会进行分组和比较,因此它的最好、最坏、平均的时间复杂度都是 O(nlogn)

归并算法是一种稳定的排序算法。

本文参考自《大话数据结构》,在此仅作记录,方便以后查阅,大神勿喷!

PHP 相关文章推荐
ADODB结合SMARTY使用~超级强
Nov 25 PHP
php木马攻击防御之道
Mar 24 PHP
PHP中Date获取时间不正确怎么办
Jun 05 PHP
PHP5 操作MySQL数据库基础代码
Sep 29 PHP
php 网页播放器用来播放在线视频的代码(自动判断并选择视频文件类型)
Jun 03 PHP
wamp下修改mysql访问密码的解决方法
May 07 PHP
php图片缩放实现方法
Feb 20 PHP
PHP+Memcache实现wordpress访问总数统计(非插件)
Jul 04 PHP
PHP扩展程序实现守护进程
Apr 16 PHP
thinkPHP实现递归循环栏目并按照树形结构无限极输出的方法
May 19 PHP
php输出图像的方法实例分析
Feb 16 PHP
PHP结合Ffmpeg快速搭建流媒体服务的实践记录
Oct 31 PHP
PHP排序算法之快速排序(Quick Sort)及其优化算法详解
Apr 21 #PHP
Laravel模型间关系设置分表的方法示例
Apr 21 #PHP
PHP排序算法之基数排序(Radix Sort)实例详解
Apr 21 #PHP
PHP排序算法之堆排序(Heap Sort)实例详解
Apr 21 #PHP
PHP实现Huffman编码/解码的示例代码
Apr 20 #PHP
PHP排序算法之希尔排序(Shell Sort)实例分析
Apr 20 #PHP
PHP排序算法之直接插入排序(Straight Insertion Sort)实例分析
Apr 20 #PHP
You might like
DC这些乐高系列动画电影你看过几部?
2020/04/09 欧美动漫
排序算法之PHP版快速排序、冒泡排序
2014/04/09 PHP
PHP实现的交通银行网银在线支付接口ECSHOP插件和使用例子
2014/05/10 PHP
thinkphp在php7环境下提示Cannot use ‘String’ as class name as it is reserved的解决方法
2016/09/30 PHP
PHP获取用户客户端真实IP的解决方案
2016/10/10 PHP
php注册系统和使用Xajax即时验证用户名是否被占用
2017/08/31 PHP
Centos7 Yum安装PHP7.2流程教程详解
2019/07/02 PHP
Prototype 学习 Prototype对象
2009/07/12 Javascript
Extjs3.0 checkboxGroup 动态添加item实现思路
2013/08/14 Javascript
图解js图片轮播效果
2015/12/20 Javascript
简介AngularJS中$http服务的用法
2016/02/06 Javascript
原生javascript实现匀速运动动画效果
2016/02/26 Javascript
动态加载css方法实现和深入解析
2017/01/18 Javascript
微信小程序 跳转传递数据的实例
2017/07/06 Javascript
JavaScript中变量提升与函数提升经典实例分析
2018/07/26 Javascript
Node爬取大批量文件的方法示例
2019/06/28 Javascript
js全屏事件fullscreenchange 实现全屏、退出全屏操作
2019/09/17 Javascript
vue-next/runtime-core 源码阅读指南详解
2019/10/25 Javascript
如何在vue中使用video.js播放m3u8格式的视频
2021/02/01 Vue.js
Python实现统计给定列表中指定数字出现次数的方法
2018/04/11 Python
python实现连续图文识别
2018/12/18 Python
我们为什么要减少Python中循环的使用
2019/07/10 Python
通过 Django Pagination 实现简单分页功能
2019/11/11 Python
Python龙贝格法求积分实例
2020/02/29 Python
基于python实现音乐播放器代码实例
2020/07/01 Python
用python爬虫批量下载pdf的实现
2020/12/01 Python
斯图尔特·韦茨曼鞋加拿大官网:Stuart Weitzman加拿大
2019/10/13 全球购物
土木工程毕业生自荐信
2013/11/12 职场文书
精彩的英文自荐信
2014/01/30 职场文书
医德医风演讲稿
2014/05/20 职场文书
2014年科研工作总结
2014/12/03 职场文书
公司捐书倡议书
2015/04/27 职场文书
2015年外贸业务员工作总结范文
2015/05/23 职场文书
医院党建工作总结2015
2015/05/26 职场文书
2019年健身俱乐部的创业计划书
2019/08/26 职场文书
利用python调用摄像头的实例分析
2021/06/07 Python