堆以及php实现堆排序

什么是堆
这里的堆(二叉堆),指得不是堆栈的那个堆,而是一种数据结构。

堆可以视为一棵完全的二叉树,完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素.

数组与堆之间的关系
堆
二叉堆一般分为两种:最大堆和最小堆。

什么是最大堆

堆中每个父节点的元素值都大于等于其孩子结点(如果存在),这样的堆就是一个最大堆

因此,最大堆中的最大元素值出现在根结点(堆顶)

节点与数组索引关系

对于给定的某个结点的下标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),
但是堆排序并不是稳定排序(排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前 和排序后他们的相对位置不发生变化)


参考资料:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值