php堆是什么,PHP 堆与堆排序的详解

堆排序:堆排序是利用堆的性质进行的一种选择排序。下面先讨论一下堆。

1.堆

堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:

Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]

即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。

堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。

2.堆排序的思想

利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。

其基本思想为(大顶堆):

1)将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无须区;

2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];

3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

操作过程如下:

1)初始化堆:将R[1..n]构造为堆;

2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。

因此对于堆排序,最重要的两个操作就是构造初始堆和调整堆,其实构造初始堆事实上也是调整堆的过程,只不过构造初始堆是对所有的非叶节点都进行调整。

堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。学习堆排序前,先讲解下什么是数据结构中的二叉堆。

PHP 堆管理代码如下:

classheep{

staticfunctionadd(&$arr,$one){

$arr[] =$one;

self::up($arr,count($arr) -1);

}

// 下沉

staticfunctiondel(&$arr){

$arr[0] =array_pop($arr);

self::down($arr,0,count($arr)-1);

}

staticfunctionswap(&$arr,$i,$p){

$tmp=$arr[$i];

$arr[$i] =$arr[$p];

$arr[$p] =$tmp;

}

// 增加元素 上浮

staticfunctionup(&$arr,$i){

$p=floor(($i-1)/2);

while($p>= 0 &&$i> 0 &&$arr[$p] >$arr[$i] ){

self::swap($arr,$i,$p);

$i=$p;

$p=floor(($i-1)/2);

}

}

// 下沉 $i开始 $n结束

staticfunctiondown(&$arr,$i,$n){

$l= 2*$i+ 1;

while($l<=$n){

if($l+1 <=$n&&$arr[$l+1]

if($arr[$l] >$arr[$i] )break;

self::swap($arr,$i,$l);

$i=$l;

$l= 2*$i+ 1;

}

}

// 将数组变成堆

staticfunctionmake(&$arr){

$n=count($arr)-1;

for($i=$n/ 2 – 1;$i>= 0;$i–)

self::down($arr,$i,$n);

}

// 将堆进行排序

staticfunctionsort(&$arr){

$n=count($arr)-1;

for($i=$n;$i>= 0;$i–){

self::swap($arr,0,$i);

self::down($arr,0,$i-1);

}

}

}

$arr= [10,40,30];

$arr=array();

heep::add($arr,40);

heep::add($arr,10);

heep::add($arr,30);

heep::add($arr,15);

heep::add($arr,8);

heep::add($arr,50);

heep::add($arr,20);

heep::add($arr,3);

echojoin(',',$arr),'
';

heep::del($arr);

heep::del($arr);

heep::del($arr);

echojoin(',',$arr),'
';

//phpfensi.com

heep::sort($arr);

echojoin(',',$arr),'
';

$arr= [40,10,30];

heep::make($arr);

echojoin(',',$arr),'
';

假设n为当前数组的key则,n的父节点为 n>>1 或者 n/2(整除);n的左子节点l= n<<1 或 l=n*2,n的右子节点r=(n<<1)+1 或 r=l+1,代码如下:

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

数组$arr的原形态结构如下:

1

/

8 7

/ /

2 3 4 6

/

5 9

heapsort($arr);print_r($arr);

排序后生成标准的小顶堆结构如下:

1

/

2 3

/ /

4 5 6 7

/

8 9

既数组:array(1,2,3,4,5,6,7,8,9):代码如下:

functionheapsort(&$arr)

{

//求最后一个元素位

$last=count($arr);

//堆排序中通常忽略$arr[0]

array_unshift($arr,0);

//最后一个非叶子节点

$i=$last>>1;

//整理成大顶堆,最大的数整到堆顶,并将最大数和堆尾交换,并在之后的计算中忽略数组后端的最大数(last),直到堆顶(last=堆顶)

while(true)

{

adjustnode($i,$last,$arr);

if($i>1)

{

//移动节点指针,遍历所有非叶子节点

$i–;

}

else

{

//临界点last=1,既所有排序完成

if($last==1)break;

//当i为1时表示每一次的堆整理都将得到最大数(堆顶,$arr[1]),重复在根节点调整堆

swap($arr[$last],$arr[1]);

//在数组尾部按大小顺序保留最大数,定义临界点last,以免整理堆时重新打乱数组后面已排序好的元素

$last–;

}

}

//弹出第一个数组元素

array_shift($arr);

}

//整理当前树节点($n),临界点$last之后为已排序好的元素

functionadjustnode($n,$last,&$arr)

{

$l=$n<<1;//$n的左孩子位

if(!isset($arr[$l])||$l>$last)return;

$r=$l+1;//$n的右孩子位

//如果右孩子比左孩子大,则让父节点的右孩子比

if($r<=$last&&$arr[$r]>$arr[$l])$l=$r;

//如果其中子节点$l比父节点$n大,则与父节点$n交换

if($arr[$l]>$arr[$n])

{

//子节点($l)的值与父节点($n)的值交换

swap($arr[$l],$arr[$n]);

//交换后父节点($n)的值($arr[$n])可能还小于原子节点($l)的子节点的值,所以还需对原子节点($l)的子节点进行调整,用递归实现

adjustnode($l,$last,$arr);

}

}

//交换两个值

functionswap(&$a,&$b)

{

$a=$a^$b;

$b=$a^$b;

$a=$a^$b;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257484.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Odoo (OpenERP/TinyERP)-10.0 (Debian 8)

平台&#xff1a; Ubuntu 类型&#xff1a; 虚拟机镜像 软件包&#xff1a; odoo-10.0commercial erp odoo open source openerp tinyerp服务优惠价: 按服务商许可协议 云服务器费用:查看费用 立即部署产品详情 产品介绍Odoo https://www.odoo.com/ &#xff08;前Op…

iOS开发- 蓝牙后台接收数据(BLE4.0)

最近在做一个蓝牙相关的项目, 需要在应用进入后台, 或者手机属于锁屏状态的情况下, 仍然保持蓝牙连接, 并且能正常接收数据。 本来以后会很麻烦, 但是学习了下..发现就2步而已。简单的不能再简单了。 好了。下面是具体实现办法。 1.在xxx-info.plist文件中, 新建一行 Required…

贪心(数据结构):COGS 468. [NOI2010]超级钢琴

★★★☆ 输入文件&#xff1a;piano.in 输出文件&#xff1a;piano.out 简单对比 时间限制&#xff1a;2 s 内存限制&#xff1a;512 MB 超级钢琴 【问题描述】 小Z是一个小有名气的钢琴家&#xff0c;最近C博士送给了小Z一架超级钢琴&#xff0c;小Z希望能够用这架…

java实现选择排序 带打印,选择排序算法的JAVA实现

选择排序算法的JAVA实现package Utils.Sort;/***利用选择排序法对数组排序&#xff0c;数组中元素必须实现了Comparable接口。*/public class ChooseSort implements SortStrategy{/***对数组obj中的元素以选择排序算法进行排序*/public void sort(Comparable[] obj){if (obj …

angularjs初始化时不显示模板内容, 不显示html, 不显示template

template的内容可能在需要的数据准备好之前就显示出来了, ng-cloak可以解决这个问题 ng-cloak <div id"template1" ng-cloak>{{ hello }}</div> <div id"template2" class"ng-cloak">{{ world }}</div>

左右箭头滑动列表

//slideshow 左右箭头滑动一组li焦点图 autoSlide();function autoSlide(){clearAutoSsetInterval(autoFunS,5000);}function autoFunS(){var loc$(".slideshow-box ul").css("left");if(loc"-2370px"){loc"1185";}var newlocparseInt…

20159206《网络攻防实践》第四周学习总结

20159206《网络攻防实践》第四周学习总结 教材学习内容总结 本章主要介绍了网络嗅探和协议分析 网络嗅探是一种常用的窃听技术&#xff0c;利用计算机的网络接口截获目的地为其他计算机的数据报文&#xff0c;以监听数据流中所包含的用户账户密码或私密信息等。 网络泄滩具有很…

四六级php,详解四六级查询API+网页

这个API是第三方API&#xff0c;第三方API的工作原理大都基于此&#xff0c;本文主要起一反三之作用&#xff0c;代码的不处周之还望及时指出。开发环境&#xff1a;WinServer2012 php7.0 Apache2.4.8思路&#xff1a;向官方查询界面传递参数&#xff0c;使用curl抓取结果网页…

终于把joomla 的 protostar 模版的菜单,从垂直改到水平了

protostar-applying-menu-class-suffixes-horizontal-vs-vertical-menus.html joomla 3.7.5 附带的这个template , 菜单丑的要死。 估计是新改的。 看网上的其他站点都没这毛病。 最后终于找到解决方法了。“ nav-pills“ 前面是有空格的 To make the menu horizonal, you can …

Find non-overlap jobs with max cost

Given a set of n jobs with [start time, end time, cost] find a subset so that no 2 jobs overlap and the cost is maximum.Job: &#xff08;start_time, end_time] --- cost 如果只是求maxCost, 一维就可以做。 但是如果要知道有选了哪些job&#xff0c;则需要存成二维。…

php 跨区域,PHP跨时区的功能实现

现在有一个跨时区的应用&#xff0c;不同时区登录的用户需要看到自己时区的时间&#xff0c;同时也要能够进行时区的切换。我的思路是&#xff0c;系统中所有存储的时间都是GMT(UTC)时间&#xff0c;用户登录时&#xff0c;根据用户所在的时区进行对应的显示。首先了解一下PHP中…

js实现向上滚动效果

源码&#xff1a;<style type"text/css"> #up_zzjs{border:1px solid #ccc;width:170px;height:182px;line-height:20px;overflow:hidden;} #up_zzjs #up_li{list-style-type:none;margin:0;padding:0;margin-left:6px;} /*系统支持ie8就选line-heigh…

利用数据的商业智能分析工具

商业智能可以定义为获取和转换原始数据的技术和工具&#xff0c;这些信息可以为业务运营提供有意义的好处。 商业智能的发展 商业智能&#xff08;BI&#xff09;是一个可追溯到19世纪中期的术语&#xff0c;基本上是一样的定义。但作为结构化数据的自动化处理的参考&#xff0…

管理之道(三) - 不要吝惜赞美

多一句赞美 人们相互希望得越多&#xff0c;想要给予对方的越多……就必定越亲密。   几天前&#xff0c;我和一位朋友在纽约搭计程车&#xff0c;下车时&#xff0c;朋友对司机说&#xff1a;“谢谢&#xff0c;搭你的车十分舒适。”这司机听了愣了一愣&#xff0c;然后说&a…

优酷视频整段代理php,thinkphp仿优酷带数据源码|php仿优酷视频源码带后台功能强大...

本项目是仿优酷官网&#xff0c;优酷官网是一个集多种知识面为一体的网站&#xff0c;能全面的锻炼我们的技能,所以我们决定仿优酷网。本项目后台主要实现了&#xff1a;用户管理、分类管理、视频管理、评论管理、权限管理、轮播管理、网站配置和广告管理以及登录退出等模块。前…

Centos7安装Oracle JDK

查看Linux是否自带的JDK&#xff0c;如有openJDK&#xff0c;则卸载1 java -version 1 rpm -qa | grep -E ^open[jre|jdk]|j[re|dk] 卸载openjdk1 su root 2 3 yum -y remove java java-1.7.0-openjdk 下载oracle jdk1 wget --no-cookies --header "Cookie: oraclelice…

前端每周清单第 30 期:WebVR 指南,Vue 代码分割范式,理想的 React 架构特性

前端每周清单专注前端领域内容&#xff0c;以对外文资料的搜集为主&#xff0c;帮助开发者了解一周前端热点&#xff1b;分为新闻热点、开发教程、工程实践、深度阅读、开源项目、巅峰人生等栏目。欢迎关注【前端之巅】微信公众号&#xff08;ID&#xff1a;frontshow&#xff…

Oracle(3)——Oracle图形界面工具创建数据库

具体操作步骤详情&#xff1a; 1.图形界面工具首界面 Database Configuration Assistant 点击下一步 2.默认 点击下一步 3.默认 点击下一步 4.设置全局数据库名、SID 为新建数据库起一个“全局数据库名”&#xff0c;比如这里对数据库名和SID&#xff1a;FKXT 点击下一步 5.设置…

rsa 加密 js php,security.js+RSA做出加密功能

这次给大家带来security.jsRSA做出加密功能&#xff0c;的注意事项有哪些&#xff0c;下面就是实战案例&#xff0c;一起来看一下。在项目中遇到要对用户输入的密码进行RSA加密的需求&#xff0c;总结一下实现过程&#xff1a;JS rsa加密加密//引入security.js文件var btn doc…

多线程面试题系列(12):多线程同步内功心法——PV操作上

上面的文章讲解了在Windows系统下实现多线程同步互斥的方法&#xff0c;为了提高在实际问题中分析和思考多个线程之间同步互斥问题的能力&#xff0c;接下来将讲解PV操作&#xff0c;这也是操作系统中的重点和难点。本文将会先简要介绍下PV操作的来源和基本使用方法&#xff0c…