必须实现最大堆:一、数组类封装(零索引),含siftup/siftdown;二、原地堆化(递归调整+构建);三、一索引兼容实现;四、函数式轻量实现。

如果您需要在PHP中构建一个支持高效插入和提取最大值的数据结构,则必须实现符合完全二叉树性质且满足父节点值不小于子节点值的结构。以下是实现最大堆数据结构的多种方法:
一、基于数组的类封装实现
该方法将堆逻辑完全封装为一个独立类,使用零起始索引数组存储元素,并通过siftUp与siftDown维护堆序性。所有操作均围绕父子索引关系展开,具备清晰的抽象边界和可复用性。
1、定义私有属性$heap数组和$size计数器,初始化为空数组与0。
2、insert($value)方法中,将新值追加至数组末尾,调用siftUp($this->size)后递增$size。
3、siftUp($index)中,循环计算父索引$parentIndex = (int)(($index - 1) / 2),当$heap[$index] > $heap[$parentIndex]时执行swap并更新$index为$parentIndex。
4、delete()方法中,若堆为空返回null;否则保存堆顶值,将末尾元素移至堆顶,$size减1,再调用siftDown(0)。
5、siftDown($index)中,当左子索引$left = $index * 2 + 1
二、函数式原地建堆实现
该方法不依赖类结构,直接对输入数组进行原地调整,适用于一次性构建静态最大堆场景。利用自底向上方式对非叶节点逐个执行maxHeapify,确保每个子树满足最大堆性质。
1、定义maxHeapAdjust(&$arr, $i, $heapSize),设$largest = $i,计算$left = 2 * $i + 1、$right = 2 * $i + 2。
2、若$left $arr[$largest],更新$largest = $left。
3、若$right $arr[$largest],更新$largest = $right。
4、若$largest ≠ $i,交换$arr[$i]与$arr[$largest],并递归调用maxHeapAdjust($arr, $largest, $heapSize)。
5、定义buildMaxHeap(&$arr),取最后一个非叶节点索引$lastParent = (int)(count($arr) / 2) - 1,从该索引递减至0,对每个$i调用maxHeapAdjust($arr, $i, count($arr))。
三、索引偏移一的兼容实现
该方法采用传统教材中以1为起始索引的堆表示法,避免负索引或整除误差问题,适合教学演示或与伪代码严格对齐的场景。数组第0位保留空值或忽略,实际数据从下标1开始填充。
1、初始化数组时预留位置0,如$arr = [null, 53, 17, 78, 9]。
2、对于任意节点索引$i,其左子为$left = 2 * $i,右子为$right = 2 * $i + 1,父节点为$parent = (int)($i / 2)。
3、insert操作将值置于$arr[count($arr)],令$j = count($arr)-1,$i = (int)($j / 2),当$arr[$j] > $arr[$i]且$i ≥ 1时持续交换并更新$j = $i、$i = (int)($j / 2)。
4、delete操作将$arr[1]暂存,赋$arr[1] = $arr[count($arr)-1],unset末尾元素,然后从$i = 1开始,设$j = 2 * $i,若$arr[$j+1]存在且大于$arr[$j]则$j++,若$arr[$i]
四、使用SplMaxHeap扩展类实现
该方法借助PHP标准库提供的SplMaxHeap类,无需手动编写堆化逻辑,适用于快速原型开发或对性能要求不极端的业务场景。该类已实现O(log n)插入与O(log n)提取最大值,并自动维护堆序。
1、声明类继承SplMaxHeap,重写compare($value1, $value2)方法,返回$value1 - $value2以启用最大堆行为。
2、实例化对象后,调用insert($value)添加元素,内部自动完成上浮调整。
3、调用top()获取最大值而不移除,调用extract()弹出并返回堆顶最大值,内部自动完成下沉调整。
4、调用count()获取当前堆大小,调用isEmpty()判断是否为空,所有方法均保证线程安全与异常健壮性。
五、面向过程的极简实现
该方法仅用最少代码行数达成核心功能,省略错误处理与封装,适合嵌入脚本或学习堆原理本质。所有逻辑集中于两个核心函数:heapify_up和heapify_down,依赖全局数组变量模拟堆状态。
1、定义全局数组$heap = []和$len = 0。
2、push($x)函数中执行$heap[$len++] = $x;随后$cur = $len - 1;$par = (int)(($cur - 1) / 2);while($cur > 0 && $heap[$cur] > $heap[$par]) { swap($heap, $cur, $par); $cur = $par; $par = (int)(($cur - 1) / 2); }。
3、pop()函数中若$len == 0返回null;$ret = $heap[0];$heap[0] = $heap[--$len];$cur = 0;while(true) { $left = $cur * 2 + 1;$right = $cur * 2 + 2;$largest = $cur;if($left $heap[$largest]) $largest = $left;if($right $heap[$largest]) $largest = $right;if($largest == $cur) break;swap($heap, $cur, $largest);$cur = $largest; };return $ret。
4、swap(&$a, $i, $j)函数中使用临时变量交换$a[$i]与$a[$j]的值。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











