PHP实现堆排序:原理、代码与性能分析

周叙
周叙
发布时间:2026-10-14 | 5人浏览过
原创

本文详解PHP堆排序的核心逻辑,通过大顶堆构建与元素交换实现数组有序排列。代码包含完整的节点调整与递归维护机制,适用于理解经典排序算法在PHP中的具体落地。

堆排序核心原理

堆排序(Heapsort)是利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。在PHP排序中,通常采用大顶堆(Max Heap),即根节点的值最大,从而将最大值逐步移至数组末端,实现升序排列。

以下是堆结构中关键节点的索引计算规则(假设从索引1开始计数):

  • 父节点:对于当前节点 $n$,其父节点索引为 n >> 1(即 n / 2 整除)。
  • 左子节点:索引为 n << 1(即 n * 2)。
  • 右子节点:索引为 (n << 1) + 1(即 n * 2 + 1)。

例如,初始数组 $arr = array(1,8,7,2,3,4,6,5,9),若将其视为从索引1开始的堆结构,其原始形态如下:

        1
       /
      8     7
     / \   /
    2   3 4 6
   /
  5  9

经过堆排序调整后,目标状态为小顶堆结构对应的升序数组 array(1,2,3,4,5,6,7,8,9),但内部过程需通过构建大顶堆来实现。

PHP堆排序完整实现代码

以下代码实现了标准的堆排序算法。为了提高可读性,未进行极限性能优化,保留了清晰的逻辑结构。代码主要包含三个部分:主排序函数、节点调整函数和交换函数。

复制代码代码如下:
function heapsort(&$amp;arr) { //求最后一个元素位 $last=count($amp;arr); //堆排序中通常忽略$arr[0],因此向前插入一个占位符 array_unshift($amp;arr,0); //最后一个非叶子节点索引,从后向前处理 $i=$last>>1; //整理成大顶堆,最大的数整到堆顶,并将最大数和堆尾交换,并在之后的计算中忽略数组后端的最大数(last),直到堆顶(last=堆顶) while(true) { adjustnode($i,$last,$amp;arr); if($i>1) { //移动节点指针,遍历所有非叶子节点 $i--; } else { //临界点last=1,既所有排序完成 if($last==1)break; //当i为1时表示每一次的堆整理都将得到最大数(堆顶,$amp;arr[1]),重复在根节点调整堆 swap($amp;arr[$last],$amp;arr[1]); //在数组尾部按大小顺序保留最大数,定义临界点last,以免整理堆时重新打乱数组后面已排序好的元素 $last--; } } //弹出第一个数组元素(占位符) array_shift($amp;arr); } //整理当前树节点($n),临界点$last之后为已排序好的元素 function adjustnode($n,$last,&$amp;arr) { $l=$n<<1;        //$n的左孩子位 if(!isset($amp;arr[$l])||$l>$last) return ; $r=$l+1;        //$n的右孩子位 //如果右孩子比左孩子大,则让父节点的右孩子比 if($r<=$last&&$amp;arr[$r]>$amp;arr[$l]) $l=$r; //如果其中子节点$l比父节点$n大,则与父节点$n交换 if($amp;arr[$l]>$amp;arr[$n])                 { //子节点($l)的值与父节点($n)的值交换 swap($amp;arr[$l],$amp;arr[$n]); //交换后父节点($n)的值($amp;arr[$n])可能还小于原子节点($l)的子节点的值,所以还需对原子节点($l)的子节点进行调整,用递归实现 adjustnode($l,$last,$amp;arr); } } //交换两个值 function swap(&$amp;a,&$amp;b) { $a=$a ^ $b; $b=$a ^ $b; $a=$a ^ $b; }
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表