演算法與資料結構之原地堆排序

吳軍旗發表於2018-06-01

今天比較有感悟的是吳軍老師《矽谷來信》的一句話:走完最後的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
複製程式碼

-------------------------華麗的分割線--------------------

看完的朋友可以點個喜歡/關注,您的支援是對我最大的鼓勵。

個人部落格番茄技術小棧掘金主頁

想了解更多,歡迎關注我的微信公眾號:番茄技術小棧

番茄技術小棧

相關文章