数据结构(9)-优先队列

本文的优先队列基于大顶堆实现:数据结构(8)-二叉堆

优先队列是一种用来维护一组元素构成的结合S的数据结构,其中每个元素都有一个关键字key,元素之间的比较都是通过key来比较的。优先队列包括最大优先队列和最小优先队列,优先队列的应用比较广泛,比如作业系统中的调度程序,当一个作业完成后,需要在所有等待调度的作业中选择一个优先级最高的作业来执行,并且也可以添加一个新的作业到作业的优先队列中。Java中,PriorityQueue的底层数据结构就是堆(默认为小顶堆)。

一、基本操作

对于优先队列,只实现两个外部可调用的基本操作:一是插入元素,二是删除最大元素。

  • 插入元素
    我们将新元素添加到数组末尾,增加堆的大小并让这个新元素上浮到合适的位置
    在这里插入图片描述
  • 删除最大元素
    我们从数组顶端删去最大的元素并将数组的最后一个元素放到顶端,减少堆的大小并且让这个元素下沉到合适的位置
    在这里插入图片描述

二、Java代码实现

//大顶堆实现的优先队列
public class MaxPQ  {
    //二叉堆节点数
    int size;
    //构造二叉堆的数组
    int[] a;
    //二叉堆最大大小
    int max;

    public BinaryHeap(int length) {
        //初始节点数为0
        size = 0;
        //初始化有长度的二叉堆数组[长度加一是因为节点以1开始]
        max = length + 1;
        a = new int[max];
    }


    /**
     * 判断是否为空堆
     */
    public boolean isEmpty() {
        return size == 0;
    }
    /**
     * 堆大小
     */
    public int size() {
        return size;
    }
    /**
     *  k节点上游调整堆平衡
     */
    public void swim(int k) {
        while (k > 1 && a[k] > a[k/2]) {
            //当k节点不为根节点且大于其父节点时上浮到父节点位置
            int temp = a[k];
            a[k] = a[k / 2];
            a[k / 2] = temp;
            //重新定位节点位置
            k = k / 2;
        }
    }

    /**
     * k节点下浮调整堆平衡
     */
    public void sink(int k) {
        while (2 * k <= size) {
            //目前j为左子节点
            int j = 2 * k;
            //比较左子节点和右子节点哪个大,将节点位置调整为大的子节点
            if (j < size && a[j] < a[j + 1]) {
                j++;
            }
            //j代表的子节点和父节点k比较,调整位置
            if (a[k] >= a[j]) {
                break;
            }
            //k < j
            int temp = a[k];
            a[j] = a[k];
            a[k] = temp;
            //重新定位k的位置
            k = j;
        }
    }

    /**
     * 判断堆是否饱和
     */
    public boolean isFull() {
        return size >= max;
    }
    /**
     * 在堆低插入数据并且调整堆平衡
     */
    public void insert(int value) {
        if (isFull()) {
            return;
        }
        a[++size] = value;
        //调整该节点位置使其平衡
        swim(size);
    }

    /**
     *  删除根节点并调整平衡
     */
    public int delMax() {
        if (!isEmpty()) {
            int rootValue = a[1];
            //交换根节点和最后一个节点(最小节点)的位置并将堆大小减小
            a[1] = a[size];
            a[size] = rootValue;
            //将堆最后一个节点置为0标识被删除,且把堆节点数减少1
            a[size--] = 0;

            //将根节点下浮并调整堆平衡
            sink(1);

            return rootValue;
        }

        return 0;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringRong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值