数据结构之优先队列

一、数据结构

二叉堆

首先,二叉堆是一颗被完全填满的二叉树

  • 有任意节点的左节点为2i+1,右节点为2i+2
  • 在一个堆中,对于每一个节点X,X的父亲中关键字小于(或等于)X中的关键字,根节点除外。
  • insert操作:上滤,从下往上寻找可以插入的节点;
  • delete操作:下滤,删除根,递归根节点的最小儿子补位。
  • 定理:包含2^(k+1)-1个节点,高为h的理想二叉树的节点的高度和为2^(k+1)-1-(h+1);

d-堆

d-堆是二叉堆的简单推广,它就像一个二叉堆,只是所有节点都有d个儿子,二叉堆是2-堆。

数据显示,4-堆可以胜过二叉堆。

左式堆

被设计用来有效的支持合并操作。

在左式堆中,对于每一个节点X,做儿子的零路径长至少与右儿子的零路径长相等;

零路径长:任一节点X的零路径长是从X到一个不具有两个儿子的节点的最短路径长;

如何合并:

  1. 对于两个左式堆,首先递归的将具有大的根植B的堆与具有小的根植S的右子堆合并;
  2. 将合并后的堆放到S堆的右节点;
  3. 交换S堆的左右节点更新零路径长。

斜堆

是左式堆的自调节形式,斜堆不保留零路径长的概念。

二项队列

二项树Bk由一个带有儿子的B0,B1,B2...B(k-1)的根组成。与二进制一一对应,如大小为13的优先队列可以用B3,B2,B0表示,记为1101。

image.png

合并:

插入:是特殊情形的合并。

删除:

 

 

二、优先队列的应用

  1. 给定一个无序集合和一个整数k,找出第k个最大的元素;
    1. 构建二叉堆,删除k次,即为所求;
    2.  

三、标准库中的优先队列

PriorityQueue

/**
     *  插入核心方法,使用二叉堆实现,上滤
     * @param k
     * @param x
     */
    @SuppressWarnings("unchecked")
    private void siftUpComparable(int k, E x) {
        Comparable<? super E> key = (Comparable<? super E>) x;
        while (k > 0) {
            int parent = (k - 1) >>> 1;
            // 从当前堆中最后一个元素的父节点处罚,不断寻找父节点,跟要插入的值比较大小
            Object e = queue[parent];
            // 要插入的值大,跳出
            if (key.compareTo((E) e) >= 0)
                break;
            // 否则,父节点下移
            queue[k] = e;
            k = parent;
        }
        // 将插入的值放到父节点的位置
        queue[k] = key;
    }

/**
     * 删除核心方法,删除根节点后,拿出最后一个节点,
     * 循环将根节点中较小的儿子节点上移补位,最后将最后一个节点放到空出的位置
     * @param k
     * @param x
     */
    @SuppressWarnings("unchecked")
    private void siftDownComparable(int k, E x) {
        Comparable<? super E> key = (Comparable<? super E>)x;
        // 选择一半作为停止条件
        int half = size >>> 1;        // loop while a non-leaf
        while (k < half) {
            // 二叉堆性质,左节点=2i+1
            int child = (k << 1) + 1; // assume left child is least
            Object c = queue[child];
            // 右节点
            int right = child + 1;
            // 选择左右中较小的节点
            if (right < size &&
                ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
                c = queue[child = right];
            if (key.compareTo((E) c) <= 0)
                break;
            queue[k] = c;
            k = child;
        }
        queue[k] = key;
    }

参考文献:

  1. 图解二项队列,以及复杂度分析
  2. 《数据结构预算法分析描述》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值