PHP实现堆排序:原理、代码与性能分析
本文详解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;
}
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













