堆排序(php实现)

栏目: PHP · 发布时间: 8年前

内容简介:堆排序(php实现)

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种 排序 算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

简单思路

有了前一篇博客实现的堆,自然而然的想到,将给出的数组先形成一个大根堆,然后逐一的取出,后逆序的返回即可。

代码实现

<?php
// require('../Library/SortTestHelper.php');
require('../SortingAdvance/QuickSort.php');
/**
 * 最大堆
 */
class MaxHeap{


	private $data;
	private $count;

	public function __construct(){
		$this->data = array();
		$this->count = 0;
	}


	// public function __construct($arr){
	// }

	public function insert($item){

		//从1开始
        $this->data[$this->count + 1] = $item;
        $this->_shiftUp($this->count+1);
        $this->count++;
    }

    public function  extractMax(){
        $ret = $this->data[1];
        swap( $this->data, 1 , $this->count);
        $this->count--;
        $this->_shiftDown(1);
        return $ret;
    }

    public function getMax(){
        return $this->data[1];
    }

    public function isEmpty(){
        return $this->count == 0;
    }

    public function getData(){
    	return $this->data;
    }

    /**
     * [_shiftUp 新加入到堆中的元素直接放在数组后面,再与父元素比较后交换位置,直到根节点]
     * @param  [type] $k [description]
     * @return [type]    [description]
     */
	private function _shiftUp($k){
		//如果叶子节点的值比父元素大交换位置,并更新k的值
        while( $k > 1 && $this->data[(int)($k/2)] < $this->data[$k] ){
            // swap( $this->data[(int)($k/2)], $this->data[$k] );
            swap( $this->data, (int)($k/2) , $k);
            $k = (int)($k/2);
        }
    }

    /**
     * [_shiftDown 元素出堆的时候,需要维护此时的堆依然是一个大根堆, 此时将数组元素的最后一个值与第一个值交换,后从上往下维护堆的性质]
     * @param  [type] $k [description]
     * @return [type]    [description]
     */
    private function _shiftDown($k){
    	//2k代表该节点的左子节点
        while( 2*$k <= $this->count ){
            $j = 2*$k;
            //判断右节点是否存在,并且右节点大于左节点
            if( $j+1 <= $this->count && $this->data[$j+1] > $this->data[$j] ) $j ++;
            if( $this->data[$k] >= $this->data[$j] ) break;
            // swap( $this->data[$k] , $this->data[$j] );
            swap( $this->data, $k , $j );
            $k = $j;
        }
    }
}

//简单的堆排序
function headSort1(&$arr, $n){
    $head_obj = new MaxHeap();
    for ($i=0; $i < $n; $i++) {
        $head_obj->insert($arr[$i]);
    }
    //逆序输出
    for ($i=$n-1; $i >= 0; $i--) {
        $arr[$i] = $head_obj -> extractMax();
    }
}

$n = 10000;
$arr = generateRandomArray($n, 0, $n);
$copy_arr1 = $arr;
$copy_arr2 = $arr;
$copy_arr3 = $arr;
$copy_arr4 = $arr;
// $arr = generateNearlyOrderedArray($n, 100);
testSort("headSort1", "headSort1", $arr, $n);
testSort("mergeSort", "mergeSort", $copy_arr1, $n);
testSort("quickSort", "quickSort", $copy_arr2, $n);
testSort("quickSort2", "quickSort2", $copy_arr3, $n);
testSort("quickSort3", "quickSort3", $copy_arr4, $n);
?>

结果

headSort1运行的时间为:0.70801091194153s
mergeSort运行的时间为:0.94017505645752s
quickSort运行的时间为:0.30204510688782s
quickSort2运行的时间为:0.19032001495361s
quickSort3运行的时间为:0.36022400856018s

结果分析

for ($i=0; $i < $n; $i++) {
        $head_obj->insert($arr[$i]);
    }
//逆序输出
for ($i=$n-1; $i >= 0; $i--) {
	$arr[$i] = $head_obj -> extractMax();
}

这段代码进行了两次O(N logN)时间复杂度的运算,并且是将已有的数组去生成一个堆,然后借助这个堆重新赋值给数组,其实可以直接用数组去形成一个堆,然后我们就可以进行一次O(N logN)复杂度的运算。我们只需要重写一个构造函数,通过一个数组去构造它!

堆排序的优化

代码实现

<?php
require('../SortingAdvance/QuickSort.php');
/**
 * 根据已知数组最大堆
 */
class HeapSort{


	private $data;
	private $count;

	public function __construct($arr, $n){
		$this->data = array();
        $this->count = $n;
        for ($i=0; $i < $n; $i++) {
            //从1开始
            $this->data[$i+1] = $arr[$i];
        }
        //叶子节点已经是一颗大根堆了,从最后一个非叶子节点进行_shiftDown,知道根节点
        for ($i= (int)($n/2); $i >= 1 ; $i--) {
            $this->_shiftDown($i);
        }
	}


	// public function __construct($arr){
	// }

	public function insert($item){

		//从1开始
        $this->data[$this->count + 1] = $item;
        $this->_shiftUp($this->count+1);
        $this->count++;
    }

    public function  extractMax(){
        $ret = $this->data[1];
        swap( $this->data, 1 , $this->count);
        $this->count--;
        $this->_shiftDown(1);
        return $ret;
    }

    public function getMax(){
        return $this->data[1];
    }

    public function isEmpty(){
        return $this->count == 0;
    }

    public function getData(){
    	return $this->data;
    }

    /**
     * [_shiftUp 新加入到堆中的元素直接放在数组后面,再与父元素比较后交换位置,直到根节点]
     * @param  [type] $k [description]
     * @return [type]    [description]
     */
	private function _shiftUp($k){
		//如果叶子节点的值比父元素大交换位置,并更新k的值
        while( $k > 1 && $this->data[(int)($k/2)] < $this->data[$k] ){
            // swap( $this->data[(int)($k/2)], $this->data[$k] );
            swap( $this->data, (int)($k/2) , $k);
            $k = (int)($k/2);
        }
    }

    /**
     * [_shiftDown 元素出堆的时候,需要维护此时的堆依然是一个大根堆, 此时将数组元素的最后一个值与第一个值交换,后从上往下维护堆的性质]
     * @param  [type] $k [description]
     * @return [type]    [description]
     */
    private function _shiftDown($k){
    	//2k代表该节点的左子节点
        while( 2*$k <= $this->count ){
            $j = 2*$k;
            //判断右节点是否存在,并且右节点大于左节点
            if( $j+1 <= $this->count && $this->data[$j+1] > $this->data[$j] ) $j ++;
            if( $this->data[$k] >= $this->data[$j] ) break;
            // swap( $this->data[$k] , $this->data[$j] );
            swap( $this->data, $k , $j );
            $k = $j;
        }
    }
}


function headSort2(&$arr, $n){
    $head_obj = new HeapSort($arr, $n);
    for ($i=$n-1; $i >= 0; $i--) {
        $arr[$i] = $head_obj -> extractMax();
    }
}

$n = 10000;
$arr = generateRandomArray($n, 0, $n);
$copy_arr1 = $arr;
$copy_arr2 = $arr;
$copy_arr3 = $arr;
$copy_arr4 = $arr;

testSort("headSort2", "headSort2", $arr, $n);
testSort("mergeSort", "mergeSort", $copy_arr1, $n);
testSort("quickSort", "quickSort", $copy_arr2, $n);
testSort("quickSort2", "quickSort2", $copy_arr3, $n);
testSort("quickSort3", "quickSort3", $copy_arr4, $n);

?>

结果

quickSort2运行的时间为:0.12423086166382s
quickSort3运行的时间为:0.051468849182129s
headSort2运行的时间为:0.033907890319824s
mergeSort运行的时间为:0.020761013031006s
quickSort运行的时间为:0.016165018081665s
quickSort2运行的时间为:0.01316499710083s
quickSort3运行的时间为:0.026669025421143s

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python Machine Learning

Python Machine Learning

Sebastian Raschka / Packt Publishing - ebooks Account / 2015-9 / USD 44.99

About This Book Leverage Python' s most powerful open-source libraries for deep learning, data wrangling, and data visualization Learn effective strategies and best practices to improve and opti......一起来看看 《Python Machine Learning》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码