优先级队列

优先级队列 一端进,另一端出 按优先级出队

普通队列 一端进,另一端出 FIFO

我们做个约定:数字大的,优先级越高 ,优先出队

无序数组实现

要点

  1. 入队保持顺序

  2. 出队前找到优先级最高的出队,相当于一次选择排序

public class PriorityQueue1<E extends Priority> implements Queue<E> {Priority[] array;int size;public PriorityQueue1(int capacity) {array = new Priority[capacity];}@Override // O(1)public boolean offer(E e) {if (isFull()) {return false;}array[size++] = e;return true;}// 返回优先级最高的索引值private int selectMax() {int max = 0;for (int i = 1; i < size; i++) {if (array[i].priority() > array[max].priority()) {max = i;}}return max;}@Override // O(n)public E poll() {if (isEmpty()) {return null;}int max = selectMax();E e = (E) array[max];remove(max);return e;}//这里的删除操作有两种:一、如果是最大索引上的元素要被删除,则只需要将数组大小-1即可//二、如果不是最大索引上的元素要被删除,则要从要被删除的索引后面的数字集体向前移动private void remove(int index) {if (index < size - 1) { //说明不是最后一个元素System.arraycopy(array, index + 1,array, index, size - 1 - index);}array[--size] = null; // help GC}@Overridepublic E peek() {if (isEmpty()) {return null;}int max = selectMax();return (E) array[max];}@Overridepublic boolean isEmpty() {return size == 0;}@Overridepublic boolean isFull() {return size == array.length;}
}

测试用例:

    @Testpublic void poll() {PriorityQueue1<Entry> queue = new PriorityQueue1<>(5);queue.offer(new Entry("task1", 4));queue.offer(new Entry("task2", 3));queue.offer(new Entry("task3", 2));queue.offer(new Entry("task4", 5));queue.offer(new Entry("task5", 1));assertFalse(queue.offer(new Entry("task6", 7)));System.out.println(Arrays.toString(queue.array));assertEquals(5, queue.poll().priority());System.out.println(Arrays.toString(queue.array));assertEquals(4, queue.poll().priority());assertEquals(3, queue.poll().priority());assertEquals(2, queue.poll().priority());assertEquals(1, queue.poll().priority());
}

有序数组实现

实现方法与无序数组恰恰相反,对于poll操作很简单,但是在offer操作时要实现的就是插入排序的算法

要点

  1. 入队后排好序,优先级最高的排列在尾部

  2. 出队只需删除尾部元素即可

public class PriorityQueue2<E extends Priority> implements Queue<E> {Priority[] array;int size;public PriorityQueue2(int capacity) {array = new Priority[capacity];}// O(n)@Overridepublic boolean offer(E e) {if (isFull()) {return false;}insert(e);size++;return true;}// 一轮插入排序private void insert(E e) {int i = size - 1;//循环条件:1.遍历到低就退出  2.当遍历到第一次比自己低的索引时就退出while (i >= 0 && array[i].priority() > e.priority()) {//将优先级比搜索值要小都向上移动array[i + 1] = array[i];i--;}array[i + 1] = e;}// O(1)@Overridepublic E poll() {if (isEmpty()) {return null;}E e = (E) array[size - 1];array[--size] = null; // help GCreturn e;}@Overridepublic E peek() {if (isEmpty()) {return null;}return (E) array[size - 1];}@Overridepublic boolean isEmpty() {return size == 0;}@Overridepublic boolean isFull() {return size == array.length;}
}

测试用例:

    @Testpublic void poll() {PriorityQueue2<Entry> queue = new PriorityQueue2<>(5);queue.offer(new Entry("task1", 4));queue.offer(new Entry("task2", 3));queue.offer(new Entry("task3", 2));queue.offer(new Entry("task4", 5));queue.offer(new Entry("task5", 1));assertFalse(queue.offer(new Entry("task6", 7)));assertEquals("task4", queue.peek().value);assertEquals("task4", queue.poll().value);assertEquals("task1", queue.poll().value);assertEquals("task2", queue.poll().value);assertEquals("task3", queue.poll().value);assertEquals("task5", queue.poll().value);
}

堆实现

计算机科学中,堆是一种基于树的数据结构,通常用完全二叉树实现。

什么叫完全二叉树?

答:

1.除了最后一层不用满足有两个分支,其他层都要满足有两个分支

2.如果再往完全二叉树中加一个节点,那么必须靠左添加,从左往右依次填满,左边没有填满之前,右边就不能填,如图:

添加前:

添加后:

堆的特性如下:堆分为两种:大顶堆与小顶堆

  • 在大顶堆中,任意节点 C 与它的父节点 P 符合 P.value >= C.value:父节点的值>=子节点的值

  • 而小顶堆中,任意节点 C 与它的父节点 P 符合 P.value <= C.value:父节点的值<=子节点的值

  • 最顶层的节点(没有父亲)称之为 root 根节点

例1 - 满二叉树(Full Binary Tree)特点:每一层都是填满的

例2 - 完全二叉树(Complete Binary Tree)特点:最后一层可能未填满,靠左对齐

例3 - 大顶堆

例4 - 小顶堆

完全二叉树可以使用数组来表示:

那完全二叉树显然是个非线性的数据结构,但是它存储的时候可以使用线性的数组结构来存储数据:

特征

  • 如果从索引 0 开始存储节点数据

    • 节点 i 的父节点为 floor((i-1)/2),当 i>0 时

    • 节点 i 的左子节点为 2i+1,右子节点为 2i+2,当然它们得 < size

  • 如果从索引 1 开始存储节点数据

    • 节点 i 的父节点为 floor(i/2),当 i > 1 时

    • 节点 i 的左子节点为 2i,右子节点为 2i+1,同样得 < size

代码:

//利用大顶堆来实现  从索引 0 开始存储节点数据
public class PriorityQueue4<E extends Priority> implements Queue<E> {Priority[] array;int size;public PriorityQueue4(int capacity) {array = new Priority[capacity];}@Override//1.添加元素的时候,要符合条件,从左往右依次填满//2.根据规律,我们填的元素一定是在数组中最后一位添加//3.找填加元素的父类利用公式:节点 i 的父节点为 floor((i-1)/2),当 i>0 时//4.当添加的子元素值大于父类的元素值则要将父类的元素值与添加的子元素值进行交换,然后再让添加的子元素值再与上一级父类的元素值进行比较//简单来说://1. 入堆新元素, 加入到数组末尾 (索引位置 child)//2. 不断比较新加元素与它父节点(parent)优先级 (上浮)//    - 如果父节点优先级低, 则向下移动, 并找到下一个 parent//    - 直至父节点优先级更高或 child==0 为止public boolean offer(E offered) {if (isFull()) {return false;}int child = size++;int parent = (child - 1) / 2;while (child > 0 && offered.priority() > array[parent].priority()) {array[child] = array[parent];child = parent;//java整数取整就是向下取整 所以不需要调用floor函数parent = (child - 1) / 2;}array[child] = offered;return true;}//交换堆顶和尾部元素private void swap(int i, int j) {Priority t = array[i];array[i] = array[j];array[j] = t;}@Override//移除优先级最高的元素/*1. 交换堆顶和尾部元素, 让尾部元素出队2. (下潜)- 从堆顶开始, 将父元素与两个孩子较大者交换- 直到父元素大于两个孩子, 或没有孩子为止*/public E poll() {if (isEmpty()) {return null;}// 1. 交换堆顶和尾部元素swap(0, size - 1);//让尾部元素出队size--;Priority e = array[size];array[size] = null;shiftDown(0);        return (E) e;}//2. (下潜)//    - 从堆顶开始, 将父元素与两个孩子较大者交换//    - 直到父元素大于两个孩子, 或没有孩子为止void shiftDown(int parent) {//节点 i 的左子节点为 2i+1,右子节点为 2i+2,当然它们得 < sizeint left = 2 * parent + 1;int right = left + 1;int max = parent;//假设父元素优先级最高if (left < size && array[left].priority() > array[max].priority()) {max = left;}if (right < size && array[right].priority() > array[max].priority()) {max = right;}if (max != parent) {//有孩子比父亲大swap(max, parent);shiftDown(max);}}@Overridepublic E peek() {if (isEmpty()) {return null;}return (E) array[0];}@Overridepublic boolean isEmpty() {return size == 0;}@Overridepublic boolean isFull() {return size == array.length;}
}

参考代码:GitHub - 1693905917/DataStructure: 数据结构与算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/124085.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tensorflow2 GPU 安装方法

一、Tensorflow2 GPU 安装方法 1. 首先安装Anaconda3环境2. 在Anaconda Prompt 中安装tensorflow23. 验证GPU是否可以使用4. 错误解决 1. 首先安装Anaconda3环境 https://www.anaconda.com/ 2. 在Anaconda Prompt 中安装tensorflow2 conda update conda conda create -n ten…

Unity把UGUI再World模式下显示到相机最前方

Unity把UGUI再World模式下显示到相机最前方 通过脚本修改Shader 再VR里有时候要把3D的UI显示到相机最前方&#xff0c;加个UI相机会坏事&#xff0c;可以通过修改unity_GUIZTestMode来解决。 测试用例 测试用例如下&#xff1a; 场景包含一个红色的盒子&#xff0c;一个UI…

github搜索技巧

指定语言 language:java 比如我要找用java写的含有blog的内容 搜索项目名称包含关键词的内容 vue in:name 其他如项目描述跟项目文档&#xff0c;如下 组合使用 vue in:name,description,readme 根据Star 或者fork的数量来查找 总结 springboot vue stars:>1000 p…

关于字符拼接

当然&#xff0c;以下是加入了幽默注释的代码和对应的逻辑树&#xff1a; # 提示用户输入input和txt内容&#xff0c;期待用户真有输入 input_text input("请输入input文本&#xff1a;") # 好了&#xff0c;快点输入吧 txt_text input("请输入txt文本&#…

【数据结构】红黑树(C++实现)

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;数据结构 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【数据…

Android逆向学习(五)app进行动态调试

Android逆向学习&#xff08;五&#xff09;app进行动态调试 一、写在前面 非常抱歉鸽了那么久&#xff0c;前一段时间一直在忙&#xff0c;现在终于结束了&#xff0c;可以继续更新android逆向系列的&#xff0c;这个系列我会尽力做下去&#xff0c;然后如果可以的话我看看能…

华为云HECS云服务器docker环境下安装nginx

前提&#xff1a;有一台华为云服务器。 华为云HECS云服务器&#xff0c;安装docker环境&#xff0c;查看如下文章。 华为云HECS安装docker-CSDN博客 一、拉取镜像 下载最新版Nginx镜像 (其实此命令就等同于 : docker pull nginx:latest ) docker pull nginx查看镜像 dock…

SpringBoot中使用Servlet和Filter

为什么要把Servlet和Filter写在一起,因为使用方式很相似 两种方式 第一种,使用Servlet和Filter 使用Servlet 继承HttpServlet 注册Servlet 使用Filter 1.自定义过滤器 2.注册过滤器 这里注意一点 使用/**无效 至少我这2.4.5版本是这样 过滤所有请求用/* 那么其实还有…

(unordered)map和set封装(底层红黑树)

map和set封装 文章目录 map和set封装设计问题&#xff08;知其所以然&#xff09;为什么要对iterator进行封装&#xff1f;为什么要引入Self Ref Ptr这些模板参数&#xff1f;为什么是试图从non_const转变为const&#xff0c;而不是const转为non_const如何解决 为什么说能加con…

【C++】模板初阶 -- 详解

一、泛型编程 // 实现一个通用的交换函数&#xff1a; void Swap(int& left, int& right) {int temp left;left right;right temp; }void Swap(double& left, double& right) {double temp left;left right;right temp; }void Swap(char& left, ch…

PDF文件压缩软件 PDF Squeezer mac中文版​软件特点

PDF Squeezer mac是一款macOS平台上的PDF文件压缩软件&#xff0c;可以帮助用户快速地压缩PDF文件&#xff0c;从而减小文件大小&#xff0c;使其更容易共享、存储和传输。PDF Squeezer使用先进的压缩算法&#xff0c;可以在不影响文件质量的情况下减小文件大小。 PDF Squeezer…

使用Docker部署ElasticSearch7+ELK(附带ES操作操作命令集)

ElasticSearch 7ELK 程序安装Docker安装下载ES镜像提前创建挂载文件夹添加配置文件创建并启动容器可能出现的异常安装IK分词使用ElasticHD客户端工具(目前使用发现无法做增删改)安装Kibana 软件包安装安装ElasticSearch&#xff08;需要JDK1.8&#xff09;安装IK&#xff08;下…