算法学习—堆排序

// 待调整的堆 要下沉的父节点 堆的有效大小
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))
相关文章
相关标签/搜索