堆总结

二叉堆就是一种完全二叉树,存储在数组中,用下标表示位置

操作很简单,主要就是上浮下沉,来维护堆的性质(堆有序)

优先级队列

是基于二叉堆实现的,主要操作是插入和删除。插入是先插到最后,然后上浮到正确位置;删除是删堆顶,先将堆顶与堆底调换位置后再删除,然后新堆顶下沉到正确位置。(直接删顶要考虑维护堆性质,而直接删底不用,因此采用交换后删除的方式)

时间复杂度

插入和删除元素的时间复杂度为 O(logK)K 为当前二叉堆(优先级队列)中的元素总数。因为我们时间复杂度主要花费在 sink 或者 swim 上,而不管上浮还是下沉,最多也就树(堆)的高度,也就是 log 级别。

具体实现

优先级队列数据结构

public class MaxPQ
    <Key extends Comparable<Key>> {
    // 存储元素的数组
    private Key[] pq;
    // 当前 Priority Queue 中的元素个数
    private int N = 0;

    public MaxPQ(int cap) {
        // 索引 0 不用,所以多分配一个空间
        pq = (Key[]) new Comparable[cap + 1];
    }

    /* 返回当前队列中最大元素 */
    public Key max() {
        return pq[1];
    }

    /* 插入元素 e */
    public void insert(Key e) {...}

    /* 删除并返回当前队列中最大元素 */
    public Key delMax() {...}

    /* 上浮第 k 个元素,以维护最大堆性质 */
    private void swim(int k) {...}

    /* 下沉第 k 个元素,以维护最大堆性质 */
    private void sink(int k) {...}

    /* 交换数组的两个元素 */
    private void exch(int i, int j) {
        Key temp = pq[i];
        pq[i] = pq[j];
        pq[j] = temp;
    }

    /* pq[i] 是否比 pq[j] 小? */
    private boolean less(int i, int j) {
        return pq[i].compareTo(pq[j]) < 0;
    }

    /* 还有 left, right, parent 三个方法 */
}

插入

删除

上浮

下沉

python大根堆

py没有大根堆。存入负权值,用小根堆实现大根堆

使用:

最后更新于