欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

堆以及php实现堆排序

程序员文章站 2022-06-06 20:45:35
...

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

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

数组与堆之间的关系
堆以及php实现堆排序
二叉堆一般分为两种:最大堆和最小堆。

什么是最大堆

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

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

节点与数组索引关系

对于给定的某个结点的下标i,可以很容易的计算出这个结点的父结点、孩子结点的下标,而且计算公式很漂亮很简约(以1为开始下标)
堆以及php实现堆排序

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


参考资料: