php实现堆排序算法

原创 2017年12月11日 14:16:40

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

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小白可能比较懵,大神可能也不屑,哈哈哈

PHP堆排序实现与分析

什么是最大堆 堆可以视为一棵完全的二叉树,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素. 数组与堆之间的关系: 二叉堆一般分为两种:最大堆和最小堆。 最大...
  • wuxing26jiayou
  • wuxing26jiayou
  • 2017年06月02日 16:25
  • 373

PHP实现排序算法----堆排序(Heap Sort)

算法引进:在这里我直接引用《大话数据结构》里面的开头:在前面讲到 简单选择排序 ,它在待排序的 n 个记录中选择一个最小的记录需要比较 n - 1 次,本来这也可以理解,查找第一个数据需要比较这么多次...
  • baidu_30000217
  • baidu_30000217
  • 2016年11月08日 21:13
  • 1799

堆排序算法及C语言实现

堆排序算法及C语言实现
  • bing_bing304
  • bing_bing304
  • 2014年11月02日 11:17
  • 2724

【排序算法】堆排序原理及Java实现

1、基本思想堆是一种特殊的树形数据结构,其每个节点都有一个值,通常提到的堆都是指一颗完全二叉树,根结点的值小于(或大于)两个子节点的值,同时,根节点的两个子树也分别是一个堆。 堆排序就是利用堆(...
  • jianyuerensheng
  • jianyuerensheng
  • 2016年04月27日 18:34
  • 7510

【数据结构与算法】内部排序之三:堆排序(含完整源码)

堆排序、快速排序、归并排序(下篇会写这两种排序算法)的平均时间复杂度都为O(n*logn)。要弄清楚堆排序,就要先了解下二叉堆这种数据结构。本文不打算完全讲述二叉堆的所有操作,而是着重讲述堆排序中要用...
  • mmc_maodun
  • mmc_maodun
  • 2014年03月04日 00:01
  • 22922

基本算法_堆排序_Java实现

堆排序就是将序列调整为指定的堆,然后调整首尾元素的位置,取出末尾元素,反复进行,直到将所有元素取出,形成一个有序的序列。...
  • ljmingcom304
  • ljmingcom304
  • 2015年12月22日 14:14
  • 1864

数据结构之---C语言实现堆排序

数据结构之---C语言实现堆排序
  • u012965373
  • u012965373
  • 2015年09月08日 15:08
  • 6654

【Python排序搜索基本算法】之堆排序

堆是一种完全二叉树,堆排序是一种树形选择排序,利用了大顶堆堆顶元素最大的特点,不断取出最大元素,并调整使剩下的元素还是大顶堆,依次取出最大元素就是排好序的列表。举例如下,把序列[26,5,77,1,6...
  • littlethunder
  • littlethunder
  • 2014年04月16日 21:47
  • 8781

排序算法(七)——堆排序

基本思想 堆排序是一种树形选择排序,是对直接选择排序的改进。   首先,我们来看看什么是堆(heap): (1)堆中某个节点的值总是不大于或不小于其父节点的值; (2)堆总是一棵完全二叉树(Compl...
  • u012152619
  • u012152619
  • 2015年08月13日 08:39
  • 13845

堆排序算法代码实现

对排序算法的核心思想是: 把一个数组按照完全二叉树创建好最大堆以后,拿堆顶元素和最后一个元素(堆完全二叉树顺序存储(是个数组)\的最后一个元素)交换以后, 对于这个新的数组,除去最后面那个最大的元素(...
  • Dean_Deng
  • Dean_Deng
  • 2015年04月02日 23:04
  • 973
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:php实现堆排序算法
举报原因:
原因补充:

(最多只允许输入30个字)