堆以及php实现堆排序
程序员文章站
2022-06-06 20:45:35
...
什么是堆
这里的堆(二叉堆),指得不是堆栈的那个堆,而是一种数据结构。
堆可以视为一棵完全的二叉树,完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素.
数组与堆之间的关系
二叉堆一般分为两种:最大堆和最小堆。
什么是最大堆
堆中每个父节点的元素值都大于等于其孩子结点(如果存在),这样的堆就是一个最大堆
因此,最大堆中的最大元素值出现在根结点(堆顶)
节点与数组索引关系
对于给定的某个结点的下标i,可以很容易的计算出这个结点的父结点、孩子结点的下标,而且计算公式很漂亮很简约(以1为开始下标)
php实现代码
<?php
/**
*从$parent位置开始向下调整
*前提,以$parent为根结点的下面的任何一支都应是个最大堆
*/
function adjustNode(&$arr,$parent){
$size = count($arr)-1;
$child = $parent * 2;
if($child>$size){
return;
}
if(($child != $size) && ($arr[$child] < $arr[$child+1])){
$child++;
}
if($arr[$child]>$arr[$parent]){
swap($arr[$child],$arr[$parent]);
adjustNode($arr,$child);
}
}
function buildMaxHeap(&$arr){//从floor(N/2)个结点开始,逐一进行向下过滤操作
$size = count($arr)-1;
for($i = floor($size/2); $i > 0; $i--){
adjustNode($arr,$i);
}
}
function insertHeap(&$arr,$value){
$child = count($arr);
$arr[$child] = $value;
while($arr[floor($child/2)] < $arr[$child]){
swap($arr[floor($child/2)],$arr[$child]);
$child = floor($child/2);
}
}
/**
*为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,然后再从根结点开始进行一次从上向下的调整。
*/
function popHeap(&$arr){
$size = count($arr)-1;
$popValue = $arr[1];//先将要返回的最大值记录下来
swap($arr[$size],$arr[1]);//最后一个与第一个数据交换
unset($arr[$size]);//释放要pop的那个数据
adjustNode($arr,1);//从根节点开始向下调整堆
return $popValue;
}
function swap(&$a,&$b){
$temp = $a;
$a = $b;
$b = $temp;
}
?>
堆排序的最坏和最优情况的时间复杂度都是O(nlogn),
但是堆排序并不是稳定排序(排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前 和排序后他们的相对位置不发生变化)
参考资料:
上一篇: day 11 - 2 装饰器练习
下一篇: 数据结构——堆以及堆排序