php实现堆排序算法

来源:互联网 发布:中国网络书画论坛 编辑:程序博客网 时间:2024/05/30 04:47

最近在准备各种面试,复习了一波算法基础,关于什么是堆排序我就不多说了,这里说的很详细,不明白的可以参考一下:

https://jingyan.baidu.com/article/5225f26b057d5de6fa0908f3.html

废话不多说,贴完整代码:

<?php/** * Created by PhpStorm. * User: KeenSting * Date: 2017/12/7 * Time: 下午5:47 * Name: 梁小苍 * Phone: 13126734215 * QQ: 707719848 * File Description: 堆排序 *///节点类class Node{    public $value;  //节点值    public $left; //左子节点    public $right; //右子节点    public $father; //父节点    public $pos_in_father; //在父节点的位置,左还是右    public function __construct($num)    {        $this->value = $num;        $this->left = $this->right = $this->father = null;        $this->pos_in_father = null;//1 左,2右    }}//测试堆排序类class ATest{    private $list; //存放节点列表,节点间的关系用引用表示    private $num;  //节点数    private $result; //结果集    public function __construct(array $data)    {        $this->list = $this->result = [];        $this->num = count($data);        $this->createHeap($data,$this->num);        $this->initHeap();    }    //执行排序    public function run()    {        //交换堆顶和堆尾的节点值,移除尾部节点,加入到输出中        while(true)        {            $size = count($this->list);            if($size>2)            {                array_push($this->result,$this->list[0]->value);//堆顶的数加入结果集                $tail = array_pop($this->list);                $this->list[0]->value = $tail->value;//堆尾的数放到堆顶,在此调整                if($father = &$tail->father)//释放尾部节点,修改父节点中子节点信息,置null                {                    if($tail->pos_in_father==1)                        $father->left = null;                    else                        $father->right = null;                }                unset($tail);                $this->nodeAdjust($this->list[0]);                            }else//只有两个元素的时候就释放掉            {                array_push($this->result,$this->list[0]->value);                array_push($this->result,$this->list[1]->value);                unset($this->list);                break;            }        }        //打印降序结果        print_r($this->result);        //打印升序结果        print_r(array_reverse($this->result));    }        //创建堆结构,结果存放在list中,按从上到下,从左到右排列    private function createHeap($data,$length)    {        //使用array_shift作为队列输出        $root = new Node($data[0]);        $queue = [];        $index = 0;        array_push($queue,$root);        while($queue)        {            $father = array_shift($queue);            $index++;            if($index<$length)//创建左节点            {                $node1 = new Node($data[$index]);                $father->left = $node1;                $node1->father = $father;                $node1->pos_in_father = 1;                array_push($queue,$node1);                $index++;            }            if($index<$length)//创建右节点            {                $node2 = new Node($data[$index]);                $father->right = $node2;                $node2->father = $father;                $node2->pos_in_father = 2;                array_push($queue,$node2);            }            array_push($this->list,$father);        }    }    //初始化为大顶堆    private function initHeap()    {        for($i=$this->num-1;$i>=0;$i--)        {            $tmp = &$this->list[$i];            $this->nodeAdjust($tmp);        }    }    //递归调整节点以及其子节点,保证大顶堆的特性    private function nodeAdjust(&$tmp)    {        if(($left = &$tmp->left)!=null)//左子树        {            if(($right = &$tmp->right)!=null)//右子树在            {                if($right->value > $left->value)//先比较子节点大小                {                    if($tmp->value < $right->value)//父节点和右节点交换                    {                        $tmp_val = $right->value;                        $right->value = $tmp->value;                        $tmp->value = $tmp_val;                        $this->nodeAdjust($right);                    }                }else                {                    if($tmp->value < $left->value)//父节点和左节点交换                    {                        $tmp_val = $left->value;                        $left->value = $tmp->value;                        $tmp->value = $tmp_val;                        $this->nodeAdjust($left);                    }                }            }else{//没有右子树                if($tmp->value < $left->value)                {                    $tmp_val = $left->value;                    $left->value = $tmp->value;                    $tmp->value = $tmp_val;                    $this->nodeAdjust($left);                }            }        }else            echo '不存在子树----';    }}$a = new ATest([3,1,9,2,7,6,11,5,4,13]);$a->run();

执行结果如下:

Array

(

    [0] => 13

    [1] => 11

    [2] => 9

    [3] => 7

    [4] => 6

    [5] => 5

    [6] => 4

    [7] => 3

    [8] => 2

    [9] => 1

)

Array

(

    [0] => 1

    [1] => 2

    [2] => 3

    [3] => 4

    [4] => 5

    [5] => 6

    [6] => 7

    [7] => 9

    [8] => 11

    [9] => 13

)


程序主要思想如下:

1将给定待排序的数组初始化为节点

2初始化节点,满足大顶堆特点

3最后一个节点的值给到root节点,原来root节点的值输出,释放最后一个节点

4循环执行2,3,直到没有节点可以输出


该方法得到的是降序的排列结果,可以通过array_reverse转换为升序排列

程序里面有很多引用,php小白可能比较懵,大神可能也不屑,哈哈哈

原创粉丝点击