基于PHP实现堆排序原理及实例详解


Posted in PHP onJune 19, 2020

堆(heap)是计算机科学中一类特殊的数据结构的统称,通常是一个可以被看做一棵树的数组对象。

堆{k1,k2,ki,…,kn} (ki <= k2i,ki <= k2i+1)|(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4...n/2)

关于堆:

  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树(下面)。
  • 将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

完全二叉树

说到堆排序,就不能不提完全二叉树,这些基本概念在网上到处都是,我摘了个最简单的。。

完全二叉树:除最后一层外,每一层上的节点数均达到最大值;在最后一层上只缺少右边的若干结点。

我自己总结认为,正是因为有下面两个特点,

  • 只允许最后一层有空缺结点且空缺在右边,即叶子结点只能在层次最大的两层上出现(存储方式的规则性);
  • 若i>1,tree的双亲为tree[i div 2](其父子结点值的规律性);

才使得其进行排序非常方便。

堆排序

堆排序求升序用大顶堆,求降序用小顶堆。

本例用求降序的小顶堆来解析。

堆排序步骤如下:

1、我们将数据(49、38、65、97、76、13、27、50)建立一个数组$arr;

2、用数组$arr建立一个小顶堆(主要步骤,会在代码注释里解释,下图是用一个数组建立小顶堆的过程);

3、将堆的根(最小的元素)与最后一个叶子交换,并将堆长度减一,跳到第二步;

4、重复2-3步,直到堆中只有一个结点,排序完成。

基于PHP实现堆排序原理及实例详解

堆排序的PHP实现

//因为是数组,下标从0开始,所以,下标为n根结点的左子结点为2n+1,右子结点为2n+2; 
//初始化值,建立初始堆
$arr=array(49,38,65,97,76,13,27,50);
$arrSize=count($arr);

//将第一次排序抽出来,因为最后一次排序不需要再交换值了。
buildHeap($arr,$arrSize);

for($i=$arrSize-1;$i>0;$i--){
  swap($arr,$i,0);
  $arrSize--;
  buildHeap($arr,$arrSize);  
}

//用数组建立最小堆
function buildHeap(&$arr,$arrSize){
  //计算出最开始的下标$index,如图,为数字"97"所在位置,比较每一个子树的父结点和子结点,将最小值存入父结点中
  //从$index处对一个树进行循环比较,形成最小堆
  for($index=intval($arrSize/2)-1; $index>=0; $index--){
    //如果有左节点,将其下标存进最小值$min
    if($index*2+1<$arrSize){
      $min=$index*2+1;
      //如果有右子结点,比较左右结点的大小,如果右子结点更小,将其结点的下标记录进最小值$min
      if($index*2+2<$arrSize){
        if($arr[$index*2+2]<$arr[$min]){
          $min=$index*2+2;
        }
      }
      //将子结点中较小的和父结点比较,若子结点较小,与父结点交换位置,同时更新较小
      if($arr[$min]<$arr[$index]){
        swap($arr,$min,$index);
      }  
    }
  }
}

//此函数用来交换下数组$arr中下标为$one和$another的数据
function swap(&$arr,$one,$another){
  $tmp=$arr[$one];
  $arr[$one]=$arr[$another];
  $arr[$another]=$tmp;
}

下面是排序的最终结果:

基于PHP实现堆排序原理及实例详解

堆用来进行全排序,时间复杂度是O(nlogn)

而快排用来全排序,平均时间复杂度也是O(nlogn)

但堆排序可以用来求 TopK 时,堆的时间复杂度为O(Klog2(n),因为它只需要进行 K 轮排序即可。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
php数据库连接
Oct 09 PHP
php 获取全局变量的代码
Apr 21 PHP
PHP设计模式之命令模式的深入解析
Jun 13 PHP
神盾加密解密教程(一)PHP变量可用字符
May 28 PHP
smarty中英文多编码字符截取乱码问题解决方法
Oct 28 PHP
php发送与接收流文件的方法
Feb 11 PHP
Laravel中注册Facades的步骤详解
Mar 16 PHP
php使用ffmpeg获取视频信息并截图的实现方法
May 03 PHP
php+mysql实现的二级联动菜单效果详解
May 10 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
Sep 20 PHP
PHP大文件切割上传并带进度条功能示例
Jul 01 PHP
thinkphp3.2同时连接两个数据库的简单方法
Aug 13 PHP
深入分析PHP设计模式
Jun 15 #PHP
Laravel6.18.19如何优雅的切换发件账户
Jun 14 #PHP
Laravel服务容器绑定的几种方法总结
Jun 14 #PHP
Laravel如何实现适合Api的异常处理响应格式
Jun 14 #PHP
Yii redis集合的基本使用教程
Jun 14 #PHP
php获取小程序码的实现代码(B类接口)
Jun 13 #PHP
laravel admin实现分类树/模型树的示例代码
Jun 10 #PHP
You might like
php4与php5的区别小结(配置异同)
2011/12/20 PHP
php学习之function的用法
2012/07/14 PHP
php生成EAN_13标准条形码实例
2013/11/13 PHP
php递归法读取目录及文件的方法
2015/01/30 PHP
PHP实现长轮询消息实时推送功能代码实例讲解
2021/02/26 PHP
Jquery Ajax学习实例 向页面发出请求,返回XML格式数据
2010/03/14 Javascript
基于jquery的划词搜索实现(备忘)
2010/09/14 Javascript
javascript中关于执行环境的杂谈
2011/08/14 Javascript
node.js实现博客小爬虫的实例代码
2016/10/08 Javascript
jQuery Ajax请求后台数据并在前台接收
2016/12/10 Javascript
JS中如何实现Laravel的route函数详解
2017/02/12 Javascript
AngularJs 常用的过滤器
2017/05/15 Javascript
Vue自定义指令详解
2017/07/28 Javascript
jQuery 开发之EasyUI 添加数据的实例
2017/09/26 jQuery
深入解析vue 源码目录及构建过程分析
2019/04/24 Javascript
了解JavaScript中的选择器
2019/05/24 Javascript
解决IOS端微信H5页面软键盘弹起后页面下方留白的问题
2019/06/05 Javascript
JavaScript实现缓动动画
2020/11/25 Javascript
[04:16]DOTA2全国高校联赛16强抽签
2018/05/02 DOTA
python如何在终端里面显示一张图片
2016/08/17 Python
Python实现 多进程导入CSV数据到 MySQL
2017/02/26 Python
[原创]教女朋友学Python(一)运行环境搭建
2017/11/29 Python
Python使用requests及BeautifulSoup构建爬虫实例代码
2018/01/24 Python
使用Python的toolz库开始函数式编程的方法
2018/11/15 Python
python爬虫之验证码篇3-滑动验证码识别技术
2019/04/11 Python
tensorflow求导和梯度计算实例
2020/01/23 Python
利用Python实现朋友圈中的九宫格图片效果
2020/09/03 Python
Python绘图实现台风路径可视化代码实例
2020/10/23 Python
移风易俗倡议书
2014/04/15 职场文书
工程索赔意向书
2014/08/30 职场文书
财务整改报告范文
2014/11/05 职场文书
骆驼祥子读书笔记
2015/06/26 职场文书
预备党员入党感想
2015/08/10 职场文书
交通安全学习心得体会
2016/01/18 职场文书
CSS3点击按钮圆形进度打钩效果的实现代码
2021/03/30 HTML / CSS
pt-archiver 主键自增
2022/04/26 MySQL