java学习笔记之优先队列实现原理

普通的队列是先进先出的数据结构,而优先队列为元素赋予优先级,具有最高优先级的元素成为队列首部。

优先队列一般基于二叉堆实现。

本文会分析java中几种常见的优先队列:PriorityQueuePriorityBlockingQueueDelayQueueDelayedWorkQueue

一、二叉堆的基本原理

(一) 什么是二叉堆?

  • 完全二叉树
  • 堆的根节点的优先级最大(即最大或最小)
  • 父节点的优先级必定大于子节点,兄弟节点的优先级不确定谁大谁小
时间复杂度
插入 O(log n)
删除 O(log n)
构造 O(n)

(二) 堆的用途

  • 取最值

(三) 堆的基本操作

1. 插入

往堆插入元素,基本思想是从最后一个位置开始,通过上浮操作不断调整位置,直到满足父节点的优先级必定大于子节点这个条件

上浮

上浮是往二叉堆添加元素用到的操作,它其实是不断的调整k的位置为父元素的位置直到满足条件为止。

// 用数组表示堆
Object []objs = new Object[10];
/**
 * 上浮:
 * k表示堆的最后一个位置;
 * obj表示将要插入的元素。
 */
private void siftUp(int k, Object obj) {
    // 1. 判断k是否为根元素的位置0,如果是则直接赋值
    while(k>0) {
         // 2. 获取父元素的位置,parent = (k-1)/2
         int parent = (k-1) >>> 1;
         // 3. 如果父元素的优先级大于等于obj,跳出循环并插入obj
         if(objs[parent] >= obj) {
             break;
		 }
		 // 4. 如果父元素的优先级小于obj,将父元素赋值到k的位置,更改k为父元素的位置,继续循环
		 objs[k] = objs[parent];
		 k = parent;
    }
    // 5. 为obj赋值
    objs[k] = obj;
}
/**
 * 添加元素,不考虑数组扩容的情况。
 * 假设size表示当前堆包含的元素个数(注意不一定等于上面定义的10)
 */
public void add(Object obj) {
    if(size==0) {
        objs[0] = obj;
    } else {
        siftUp(size, obj);
        size++;
	}
}

2. 删除

删除指定位置的元素,其基本思想是从指定位置开始,把最后一个元素放到被删除元素的位置,通过下沉或者上浮操作,使得堆满足父元素优先级大于子元素的条件。

下沉

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值