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 相关文章推荐
聊天室php&amp;mysql(三)
Oct 09 PHP
php获得文件扩展名三法
Nov 25 PHP
PHP学习之字符串比较和查找
Apr 17 PHP
深入PHP5中的魔术方法详解
Jun 17 PHP
php自动识别文件编码并转换为UTF-8的方法
Jun 12 PHP
IIS下PHP的三种配置方式对比
Nov 20 PHP
PHP框架Laravel的小技巧两则
Feb 10 PHP
PHP中的类型约束介绍
May 11 PHP
PHP实现的蚂蚁爬杆路径算法代码
Dec 03 PHP
详解PHP处理密码的几种方式
Nov 30 PHP
PHP闭包定义与使用简单示例
Apr 13 PHP
PHP getID3类的使用方法学习笔记【附getID3源码下载】
Oct 18 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
php+jquery编码方面的一些心得(utf-8 gb2312)
2010/10/12 PHP
php中大括号作用介绍
2012/03/22 PHP
Laravel框架Request、Response及Session操作示例
2019/05/06 PHP
解决PHPstudy Apache无法启动的问题【亲测有效】
2020/10/30 PHP
javascript 折半查找字符在数组中的位置(有序列表)
2010/12/09 Javascript
jQuery中的.bind()、.live()和.delegate()之间区别分析
2011/06/08 Javascript
jQuery插件开发详细教程
2014/06/06 Javascript
jquery 表单验证之通过 class验证表单不为空
2015/11/02 Javascript
轻松实现javascript数据双向绑定
2015/11/11 Javascript
点击页面任何位置隐藏div的实现方法
2016/09/05 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(放大缩小)
2016/12/02 Javascript
xmlplus组件设计系列之下拉刷新(PullRefresh)(6)
2017/05/03 Javascript
微信小程序画布圆形进度条显示效果
2020/11/17 Javascript
Webpack之tree-starking 解析
2018/09/11 Javascript
mpvue项目中使用第三方UI组件库的方法
2018/09/30 Javascript
Echarts动态加载多条折线图的实现代码
2019/05/24 Javascript
JavaScript中的各种宽高属性的实现
2020/05/08 Javascript
JS时间戳与日期格式互相转换的简单方法示例
2021/01/30 Javascript
JavaScript用document.write()输出换行的示例代码
2020/11/26 Javascript
Python中str.join()简单用法示例
2018/03/20 Python
Django 实现购物车功能的示例代码
2018/10/08 Python
python 内置函数汇总详解
2019/09/16 Python
使用pytorch完成kaggle猫狗图像识别方式
2020/01/10 Python
HTML5 Canvas API中drawImage()方法的使用实例
2016/03/25 HTML / CSS
html5手机端页面可以向右滑动导致样式受影响的问题
2018/06/20 HTML / CSS
德购商城:德国进口直邮商城
2017/06/13 全球购物
AVI-8手表美国官方商店:AVI-8 USA
2019/04/10 全球购物
如何用SQL语句进行模糊查找
2015/09/25 面试题
市场营销管理制度
2014/01/29 职场文书
西北政法大学自主招生自荐信
2014/01/29 职场文书
保安队长职务说明书
2014/02/23 职场文书
护士个人自我鉴定
2014/03/24 职场文书
党的群众路线教育实践活动个人对照检查材料(校长)
2014/11/05 职场文书
2016学校先进党组织事迹材料
2016/02/29 职场文书
使用 JavaScript 制作页面效果
2021/04/21 Javascript
Java8中Stream的一些神操作
2021/11/02 Java/Android