Skip to content

📚 8.最小堆

💻 代码实现

typescript
// ps:堆的结构
class MinHeap {
    constructor() {
        /** 用数组来存储堆的形式 */
        this.heap = []
    }

    /** 交换两个节点的位置 */
    swap(i1, i2) {
        const temp = this.heap[i1]
        this.heap[i1] = this.heap[i2]
        this.heap[i2] = temp
    }

    /** 获取指定节点的父节点下标 */
    getParentIndex(i) {
        return Math.floor((i - 1) / 2)
    }

    /** 获取左孩子节点下标 */
    getLeftIndex(i) {
        return 2 * i + 1
    }

    /** 获取右孩子节点下标 */
    getRightIndex(i) {
        return 2 * i + 2
    }

    /** 上移操作 */
    shiftUp(index) {
        if (index === 0) {
            return
        }
        /** 父节点下标 */
        const parentIndex = this.getParentIndex(index)
        if (this.heap[index] < this.heap[parentIndex]) {
            this.swap(index, parentIndex)
            this.shiftUp(parentIndex)
        }
    }

    /** 下移操作 */
    shiftDown(index) {
        const leftIndex = this.getLeftIndex(index)
        const rightIndex = this.getRightIndex(index)
        let midIndex;
        if (this.heap[leftIndex] < this.heap[rightIndex]) {
            midIndex = leftIndex
        } else {
            midIndex = rightIndex
        }

        if (this.heap[index] > this.heap[midIndex]) {
            this.swap(index, midIndex)
            this.shiftDown(midIndex)
        }

    }

    /** 插入节点的值 */
    insertNode(val) {
        this.heap.push(val)
        this.shiftUp(this.heap.length - 1)
    }

    /** 去除栈顶元素  */
    pop() {
        if (this.heap.length === 0) {
            return null
        }
        if (this.heap.length === 1) {
            return this.heap.pop()
        }
        this.heap[0] = this.heap.pop()
        this.shiftDown(0)
    }

    /** 获取栈顶元素 */
    peek() {
        return this.heap[0]
    }
}
const heap = new MinHeap()

const arr = [3, 1, 2, 3, 4, 1, 4, 2, 1, 2, 4, -1]
arr.forEach((item) => {
    heap.insertNode(item)
})
console.log(heap)

// ps: 堆排序
// note:借助数组空间来实现
function heapSort(arr) {
    const minHeap = new MinHeap();
    const result = [];

    // 构建最小堆
    arr.forEach(item => {
        minHeap.insertNode(item);
    });

    // 依次取出堆顶元素,得到升序数组
    while (minHeap.heap.length > 0) {
        result.push(minHeap.peek());
        minHeap.pop();
    }

    return result;
}

console.log('heapSort(arr)', heapSort(arr))

// note: 原地堆排序
function heapSortThroughSelf(arr) {
    const heap = new MinHeap();

    // 构建最小堆
    arr.forEach(item => {
        heap.insertNode(item);
    });

    // 原地排序
    for (let i = 0; i < arr.length; i++) {
        arr[i] = heap.peek();
        heap.pop();
    }

    return arr;
}

Released under the MIT License.