算法學習—堆排序

// 待調整的堆 要下沉的父節點 堆的有效大小
function downAdjust (array, parentIndex, length) {
    // temp 保存父節點的值 用於最後的賦值
    var temp = array[parentIndex]
    var childIndex = 2 * parentIndex + 1 // 左孩子下標
    while (childIndex < length) {
        // 若是有右孩子,且右孩子大於左孩子的值 則定位到右孩子
        if(childIndex + 1 < length && array[childIndex + 1] > array[childIndex]) {
            childIndex++
        }
        // 若是父節點大於任何一個孩子的值,則直接跳出
        if (temp >= array[childIndex]) {
            break
        }
        // 無需真正交換 單向賦值便可 由於比較尚未結束
        // 父節點下面的子節點還會可能有子節點 須要接着比較 因此不能直接將父子節點的值直接交換
        array[parentIndex] = array[childIndex] // 子節點中值大的上浮
        parentIndex = childIndex // 子節點的索引賦給父節點索引
        childIndex = 2 * childIndex + 1 // 計算子節點有沒有子節點 沒有值會超出length 本次循環結束
    }
    array[parentIndex] = temp // 在這裏將原來父節點的值替換到子節點中 parentIndex是原來值大子節點的索引
}
function heapSort (array) {
    // 把無序數組構建成最大堆
    // 從最後一個非葉子節點開始 依次比較
    // Math.ceil((array.length-2)/2)最後一個非葉子節點的下標
    for (var i = Math.ceil((array.length-2)/2); i >= 0; i--) {
        downAdjust(array, i, array.length)
    }
    // 循環調整堆頂元素 移到集合尾部 調整堆產生新的堆頂
    // 最大堆堆頂是堆中最大的元素,第一次直接將該元素和第一個元素調換位置,將除最後一個元素外的剩下元素再構建成最大堆,這樣第二輪中第二大的元素就會成爲堆頂,而後將第二大元素與倒數第二個元素交換位置,以此類推。數組最後就會成爲升序數組
    for (var i = array.length-1; i > 0; i--) {
        // 最後一個元素和第一個元素進行交換
        var temp = array[i]
        array[i] = array[0]
        array[0] = temp
        // 除去已經調整的元素,將剩下的元素從新調整爲最大堆
        downAdjust(array, 0, i)
    }
    return array
}
var arr = [1,3,2,6,5,7,8,9,10,0]
console.log(heapSort(arr))
相關文章
相關標籤/搜索