当前位置: 首页 > news >正文

PriorityQueue(优先级队列)

一.概念

队列是一种先进先出的结构,在一些特殊的情况下,我们需要队列返回的可能不只是第一个那么简单,而是队列中最大或者最小的,这就需要用到优先级队列了。

优先级队列这种数据结构能够提供:返回最高优先级对象,添加新对象两种方法。

二.模拟实现

在JDK1.8PriorityQueue底层使用了堆这种数据结构,实现堆实际上就是实现优先级队列,而堆又是在完全二叉树的基础上进行了一些调整。

2.1.堆的概念

堆其实就是将二叉树的每一个树的根节点都设为当前最大/最小,我们称之为小堆/大堆。

2.2.堆的性质

堆中某个结点的值总是不大于或不小于其父节点的值;

堆总是一颗完全二叉树

2.3.堆的存储方式

从堆的概念来看可以用层序的规则来进行存储

2.4.堆的创建

2.4.1堆的向下调整

顾名思义向下调整就是往下调整,根据什么规则呢?这要看是要创建大堆还是小堆,我们以创建大堆来进行举例

我们直接来上手代码

private void shiftDown(int parent, int useSize) {int child = (2 * parent) + 1;while(child < useSize){if( child + 1 < useSize &&  elem[child] < elem[child + 1] ){child++;}if(elem[child] > elem[parent]){swap(child,parent);parent = child;child = 2* parent + 1;}else{break;}}}
 2.4.2向上调整(大根堆)

具体跟小根堆一样,一个向下一个向上。

private void shiftup(int child){int parent = (child - 1) / 2;while(child > 0){if(elem[child] > elem[parent]){swap(child,parent);child = parent;parent = (child - 1) / 2;}else{break;}}}

3.堆的创建(大根堆)

 public void creatHeap(){for (int parent = (useSize - 1 - 1) / 2; parent >= 0 ; parent--) {shiftDown(parent,useSize);}}
3.1堆的插入

堆的插入就是将要插入的元素放到最后一个有效元素的后面,要提前进行空间检查,然后进行向上调整,因为只有一条分支没有进行调整所以不用在进行递归。

 public void offer(int val){if(isFull()){this.elem = Arrays.copyOf(elem,2*elem.length);}this.elem[useSize] = val;shiftup(useSize);useSize++;}
3.2堆的删除

堆的删除实际上就是将最后一个元素和将要删除的元素进行调换,然后进行向下调整,这里在向下调整是我们是不会堆最后一个元素进行向下调整的,所以这个元素就相当于删除了。

 public int poll(){int tmp = elem[0];swap(0,useSize - 1);useSize--;shiftDown(0,useSize);return tmp;}

说了这么多,我们终于可以模拟实现优先级队列了。

public class TestHeap {private  int[] elem;private int useSize;public TestHeap(){this.elem = new int[10];}public void initHeap(int[] array){for (int i = 0; i < array.length; i++) {elem[i] = array[i];useSize++;}}public void creatHeap(){for (int parent = (useSize - 1 - 1) / 2; parent >= 0 ; parent--) {shiftDown(parent,useSize);}}private void shiftDown(int parent, int useSize) {int child = (2 * parent) + 1;while(child < useSize){if( child + 1 < useSize &&  elem[child] < elem[child + 1] ){child++;}if(elem[child] > elem[parent]){swap(child,parent);parent = child;child = 2* parent + 1;}else{break;}}}private void swap(int i, int j){int tmp = elem[i];elem[i] = elem[j];elem[j] = tmp;}public void offer(int val){if(isFull()){this.elem = Arrays.copyOf(elem,2*elem.length);}this.elem[useSize] = val;shiftup(useSize);useSize++;}private void shiftup(int child){int parent = (child - 1) / 2;while(child > 0){if(elem[child] > elem[parent]){swap(child,parent);child = parent;parent = (child - 1) / 2;}else{break;}}}public boolean isFull(){return useSize == elem.length;}public int poll(){int tmp = elem[0];swap(0,useSize - 1);useSize--;shiftDown(0,useSize);return tmp;}

三.priorityqueue特性

1. 使用时必须得导入包

package priorityQueue;

2.队列中放置的元素必须的得是能够比较大小的,否则会抛出异常

3.不能插入null对象,否则会抛出空指针异常

4.没有容量限制,其内部可以自动扩容

5.插入和删除元素的时间复杂度为O(logN)

6,队列底层使用了堆数据结构

7.队列默认情况下是小堆数据结构

如果要改成大堆结构,需要提供比较器

class IntCmp implements Comparator<Integer> {@Overridepublic int compare(Integer o1, Integer o2) {return o2.compareTo(o1);}
}

我们就以最小k个值来举例

就是在一堆数据中找到前k个最小的值,我们知道大堆的根结点都是最大的,所以我们可以找到一堆最小的数当中的最大值,我们可以先把k个值放入优先级队列(大堆结构),然后再将k后的这些值于优先级队列最大值进行比较,比根节点小,就交换。

  public  static int[] bigestk(int[] array, int k){int[] ret = new int[k];if(array == null || k <= 0){return ret;}PriorityQueue<Integer> priorityQueue =new PriorityQueue<>(new IntCmp());for (int i = 0; i < k; i++) {priorityQueue.offer(array[i]);}for (int i = k; i < array.length  ;i++) {int top = priorityQueue.peek();if(array[i] < top){priorityQueue.poll();priorityQueue.offer(array[i]);}}for (int i = 0; i < k; i++) {ret[i] = priorityQueue.poll();}return ret;}

我们再这里就提供了一个比较器。

四,常用方法

1.PriorityQueue()     创建一个空的优先级队列

2.PriorityQueue(int initialCapacity) 创建一个初始容量为 initialCapacity 大小的优先级队列,不能小于1

3.PriorityQueue(Collection<? extend E> c) 用一个集合来创建优先级队列

4. boolean offer(E e)  插入元素对象为空则抛出空指针异常

5.E peek()      获取优先级最高的元素

6.E poll();      移除优先级最高的元素,并返回

7.int size()     过去有效元素的个数

8.void clear()  清空

9.boolean isEmpty()  检测优先级队列是否为空

相关文章:

  • 远程游戏软件需要具备的几个基础功能和要求
  • Mysql读写分离(2)-中间件mycat和实践方案
  • Python字典及操作
  • 继承-C++
  • spring security解析
  • LeetCode 热题 100_最长递增子序列(87_300_中等_C++)(动态规划)
  • 小甲鱼python【p5】
  • 第八节:React HooksReact 18+新特性-React Server Components (RSC) 工作原理
  • DISCO:利用大型语言模型提取反事实
  • React-router v7 第四章(路由传参)
  • 不关“猫”如何改变外网IP?3种免重启切换IP方案
  • Spring Boot JPA 开发之Not an entity血案
  • C++学习Day0:c++简介
  • MySQL SQL 执行顺序(理论顺序)
  • 若依微服务版启动小程序后端
  • 银河麒麟系统 达梦8 安装 dlask 框架后端环境
  • [图论]生成树 引言
  • Elasticsearch使用及常见的问题
  • 基于STM32的双摄联合识别系统
  • 阿里一面:Nacos配置中心交互模型是 push 还是 pull ?(原理+源码分析)
  • 网页设计购物网站/免费的seo教程
  • 长沙企业做网站/百度电话怎么转人工
  • 网站推广策略成功的案例/长沙优化科技
  • 个人站长还有什么类型的网站可以做/网站seo排名优化软件
  • 网站公司怎么做运营/网络营销步骤
  • 如何做别人的网站/苏州seo按天扣费