基于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 相关文章推荐
Memcache 在PHP中的使用技巧
Feb 08 PHP
PHP代码网站如何防范SQL注入漏洞攻击建议分享
Mar 01 PHP
PHP中设置时区方法小结
Jun 03 PHP
php中通过数组进行高效随机抽取指定条记录的算法
Sep 09 PHP
PHP Opcache安装和配置方法介绍
May 28 PHP
PHP读书笔记_运算符详解
Jul 01 PHP
利用PHP将图片转换成base64编码的实现方法
Sep 13 PHP
thinkphp跨库操作的简单代码实例
Sep 22 PHP
万能的php分页类
Jul 06 PHP
PHP文字转图片功能原理与实现方法分析
Aug 31 PHP
Smarty模板配置实例简析
Jul 20 PHP
Laravel开启跨域请求的方法
Oct 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
PHP获取163、gmail、126等邮箱联系人地址【已测试2009.10.10】
2009/10/11 PHP
关于PHP中Object对象的笔记分享
2011/06/28 PHP
php中的常用魔术方法总结
2013/08/02 PHP
PHP+redis实现微博的拉模型案例详解
2019/07/10 PHP
通用于ie和firefox的函数 GetCurrentStyle (obj, prop)
2006/12/27 Javascript
用户注册常用javascript代码
2009/08/29 Javascript
为JavaScript添加重载函数的辅助方法
2010/07/04 Javascript
GRID拖拽行的实例代码
2013/07/18 Javascript
js 动态修改css文件用到了cssRule
2014/08/20 Javascript
Node.js环境下JavaScript实现单链表与双链表结构
2016/06/12 Javascript
JavaScript中ES6字符串扩展方法
2016/08/26 Javascript
Bootstrap select下拉联动(jQuery cxselect)
2017/01/04 Javascript
js记录点击某个按钮的次数-刷新次数为初始状态的实例
2017/02/15 Javascript
angularjs项目的页面跳转如何实现(5种方法)
2017/05/25 Javascript
实现div滚动条默认最底部以及默认最右边的示例代码
2017/11/15 Javascript
浅谈React高阶组件
2018/03/28 Javascript
Node.js引入UIBootstrap的方法示例
2018/05/11 Javascript
详解angular2.x创建项目入门指令
2018/10/11 Javascript
解决layer弹出层的内容页点击按钮跳转到新的页面问题
2019/09/14 Javascript
Layui tree 下拉菜单树的实例代码
2019/09/21 Javascript
浅谈vue生命周期共有几个阶段?分别是什么?
2020/08/07 Javascript
[38:23]完美世界DOTA2联赛循环赛 FTD vs PXG BO2第二场 11.01
2020/11/02 DOTA
详解Python with/as使用说明
2018/12/13 Python
Pyinstaller 打包发布经验总结
2020/06/02 Python
Python基于内置函数type创建新类型
2020/10/22 Python
AVON雅芳官网:世界上最大的美容化妆品公司之一
2016/11/02 全球购物
芭比波朗加拿大官方网站:Bobbi Brown Cosmetics CA
2020/11/05 全球购物
大家检讨书5000字
2014/02/03 职场文书
国际贸易专业求职信
2014/06/04 职场文书
迎国庆横幅标语
2014/10/08 职场文书
中秋客户感谢信
2015/01/22 职场文书
志愿者个人总结
2015/03/03 职场文书
强烈推荐:小学生:暑假作息时间表(值得收藏)
2019/07/09 职场文书
Python上下文管理器Content Manager
2021/06/26 Python
Mysql实现简易版搜索引擎的示例代码
2021/08/30 MySQL
漫画「处刑少女的生存之道」第3卷封面公开
2022/03/21 日漫