阅读 1163

算法与数据结构之原地堆排序

今天比较有感悟的是吴军老师《硅谷来信》的一句话:走完最后的1%,这很重要。主要介绍一下原地堆排序算法以及实现(PHP)

解释

上一次的博客 算法与数据结构堆和堆排序之堆排序 两种堆排序都需要开辟O(n)的辅助空间(构造函数中使用new分配的辅助空间),程序在开辟辅助空间和释放空间的时候也会消耗一定的时间,若能多数组进行原地堆排序,则省去了开辟和释放空间的时间,时间性能会好一些。

思路

给定一个大小为n的数组,将这个数组heapify,变为最大堆,此时数组的第一个元素就是最大值,将该值与数组最后一个元素交换位置后,对前n-1个元素进行heapify,变成最大堆,将第一个元素与数组倒数第二个元素交换位置...以此类推,最后得到的数组就是从小到大排序的。

  • 注意*

上篇博客中堆排序堆的实现是从1开始,所以当前元素(下标 i)的双亲下标为 i/2,左孩子下标为 2i,右孩子下标为 2i+1;而原地堆排序中直接对数组进行操作,数组的下标是从0开始,所以当前元素(下标i)的双亲为 (i-1)/2,左孩子下标为 2i+1,右孩子下标为 2i+2。

paste image

实现

<?php
require('../SortingAdvance/QuickSort.php');
/**
 * 原地堆排序
 */

function shiftDown(&$arr, $n, $i){
    //heapify最后一个非叶子节点, 最后一个节点为:$n-1
    while( 2*$i + 1 < $n ){
        //左节点
        $j = 2*$i + 1;
        //判断右节点是否存在,并且右节点大于左节点
        if( $j+1 < $n && $arr[$j+1] > $arr[$j] ) $j ++;
        if( $arr[$i] >= $arr[$j] ) break;
        // swap( $arr[$i] , $arr[$j] );
        swap( $arr, $i , $j );
        $i = $j;
        // print_r($arr);
    }
}

function selfHeadSort(&$arr, $n){
    //叶子节点已经heapify了,所以从(n-1)/2的非叶子节点开始
    for ($i=(int)(($n-1)/2); $i >=0 ; $i--) { 
        shiftDown($arr, $n, $i);
    }


    //$arr已经是一个堆了,下面进行原地堆排序
    //从最后一个元素开始,先和第一个元素交换,然后再对第一个元素heapify
    for ($i=$n-1; $i > 0 ; $i--) { 
        swap( $arr, 0 , $i);
        shiftDown($arr, $i, 0);
    }
}

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

testSort("selfHeadSort", "selfHeadSort", $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);

?>

复制代码

时间损耗

selfHeadSort运行的时间为:0.062602043151855s
mergeSort运行的时间为:0.670814037323s
quickSort运行的时间为:0.033109188079834s
quickSort2运行的时间为:0.021806955337524s
quickSort3运行的时间为:0.054163932800293s
复制代码

-------------------------华丽的分割线--------------------

看完的朋友可以点个喜欢/关注,您的支持是对我最大的鼓励。

个人博客番茄技术小栈掘金主页

想了解更多,欢迎关注我的微信公众号:番茄技术小栈

番茄技术小栈

文章分类
后端
文章标签