优先级队列(堆)

目录

一、概念

二、时间复杂度

三、二叉堆的特点:

四、实现代码


 

一、概念

1.优先级队列(堆)︰按照优先级的大小动态出队(动态指的是元素个数动态变化,而非固定)

2.普通队列:FIFO按照元素的入队顺序出队,先入先出。
I
现实生活中的优先级队列

例子 PriorityQueue

1.医生根据病人病情排手术排期
病情相同的情况下按照先来先排,若病情较重,优先安排手术。

二、时间复杂度

普通的链式队列 o(logn)    入队  o(1)        出队(出当前队列的最大值)(on)
优先级队列(堆) o(logn)     入队o(logn)      出队(出当前队列的最大值)(on)

基于二叉树的堆(二叉堆,应用最广泛的堆)d叉堆,索引堆

三、二叉堆的特点:

1.一颗完全二叉树,基于数组存储(元素都是靠左排列,数组中存储时不会浪费空间)

 只有完全二叉树适合使用这种结构来存储
 其他的二叉树都要用链式结构

2关于节点值:
堆中根节点值>=子树节点中的值(最大堆,大根堆)
堆中根节点值<=子树中节点的值(最小堆,小根堆)

最大堆:堆中树根>=子树中所有节点,所有子树也仍然满足堆的定义

注意点

1.节点的层次和节点的大小没有任何关系只能保证当前树中,树根是最大值。其他节点层次大小关系不确定

2.JDK中的PriorityQueue默认是基于最小堆的实现。

3.因为堆是基于数组来存储的,节点的之间的关系通过数组下标来表示从O开始编号,数组下标也是从0开始。

假设此时结点编号为i,且存在父子节点

父节点编号parent = (i - 1)/2;
左子树的编号left = 2*i+1;

右子树的编号left = 2*i+ 2;

按照数组【60,40,30,29,15,22,12,18,16,14,】保存

节点之间通过数组的索引下标来找到父子节点

四、实现代码

 /**
     * 基于动态数组实现的最大堆
     * 
     **/
public class MaxHeap {
        // 实际存储元素的数组
        private List<Integer> elementData;
        // 当前堆中元素个数
        private int size;

        public MaxHeap() {
            this(10);
        }

        public MaxHeap(int size) {
            elementData = new ArrayList<>(size);
        }

        public void add(int val) {
            // 1.直接向数组末尾添加元素
            elementData.add(val);
            size ++;
            // 2.进行元素的上浮操作
            siftUp(size - 1);
        }

        private void siftUp(int k) {
            while (k > 0 && elementData.get(k) > elementData.get(parent(k))) {
                swap(k,parent(k));
                k = parent(k);
            }
        }

        private void swap(int k, int parent) {
            int child = elementData.get(k);
            int parentVal = elementData.get(parent);
            elementData.set(k,parentVal);
            elementData.set(parent,child);
        }


        public int getSize() {
            return size;
        }

        public boolean isEmpty() {
            return size == 0;
        }

        /**
         * 找到结点k对应的父节点的索引
         * @param k
         * @return
         */
        private int parent(int k) {
            return (k - 1) >> 1;
        }

        /**
         * 找到结点k对应的左子树的索引
         * @param k
         * @return
         */
        private int leftChild(int k) {
            return (k << 1) + 1;
        }

        /**
         * 找到结点k对应的右子树的索引
         * @param k
         * @return
         */
        private int rightChild(int k) {
            return (k << 1) + 2;
        }

        @Override
        public String toString() {
            return elementData.toString();
        }
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值