优先级队列(堆)的实现

ops/2024/10/18 18:25:14/

1.什么是优先级队列

队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队
列时,可能需要优先级高的元素先出队列
,该中场景下,使用队列显然不合适,比如:在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话。
在这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。
 

2. 优先级队列模拟实现

堆实际就是在完全二叉树的基础上进行了一些调整。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

小根堆:                                                                            大根堆:

                  
堆的性质:

  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树。

 

 1)堆的向下调整

 以集合{ 27,15,19,18,28,34,65,49,25,37 }中的数据为例

1. 让parent标记需要调整的节点,child标记parent的左孩子(注意:parent如果有孩子一定先是有左孩子)

2. 如果parent的左孩子存在,即:child < end, 进行以下操作,直到parent的左孩子不存在

      parent右孩子是否存在,存在找到左右孩子中最小的孩子,让child进行标

      将parent与较小的孩子child比较,如果:

              parent小于较小的孩子child,调整结束;

              否则:交换parent与较小的孩子child,交换完成之后,parent中大的元素向下移动,可能导致子树不满足堆的性质,因此需要继续向下调整,即parent = child;child = parent*2+1; 然后继续2

 

java">   /**** @param parent 是每棵子树的根节点的下标* @param end  是每棵子树调整结束的结束条件* 向下调整的时间复杂度:O(logn)*/private void shiftDown(int parent,int end) {int child=2*parent+1;while(child<end){if(child+1<usedSize && 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;}

 

2)建堆 

java">  public void createBigHeap(int[] array) {for(int parent=(usedSize-1-1)/2;parent>=0;parent--){shiftDown(parent,usedSize);}}

 

3)堆的插入

  1. 先将元素放入到底层空间中(注意:空间不够时需要扩容)
  2.  将最后新插入的节点向上调整,直到满足堆的性质

 

java"> /*** 堆的删除:每次删除的都是优先级高的元素* 仍然要保持是大根堆*/public int poll() {if(isEmpty()){return -1;}int tmp=elem[0];swap(0,usedSize-1);usedSize--;shiftDown(0,usedSize);return tmp;}public boolean isEmpty() {return usedSize==0;}

 

4)堆的删除

  1.  将堆顶元素对堆中最后一个元素交换
  2.  将堆中有效数据个数减少一个
  3.  对堆顶元素进行向下调整

 

java">    /*** 堆的插入:仍然要保持是大根堆* @param val*/public void offer(int val) {if(isFull()){this.elem= Arrays.copyOf(elem,2*elem.length);}elem[usedSize]=val;usedSize++;shiftUp(usedSize-1);}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;}}}

 

 全部代码: 

java">import java.util.Arrays;public class PriorityQueue {public int[] elem;public int usedSize;//数组已使用的空间public PriorityQueue() {this.elem=new int[10];}//初始化elem数组public void initElem(int[] array){for(int i=0;i<elem.length;i++){elem[i]=array[i];usedSize++;}}/*** 建堆的时间复杂度:O(N)** @param array*/public void createBigHeap(int[] array) {for(int parent=(usedSize-1-1)/2;parent>=0;parent--){shiftDown(parent,usedSize);}}/**** @param parent 是每棵子树的根节点的下标* @param end  是每棵子树调整结束的结束条件* 向下调整的时间复杂度:O(logn)*/private void shiftDown(int parent,int end) {int child=2*parent+1;while(child<end){if(child+1<usedSize && 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;}/*** 堆的插入:插入完后仍然要保持是大根堆* @param val*/public void offer(int val) {if(isFull()){this.elem= Arrays.copyOf(elem,2*elem.length);}elem[usedSize]=val;usedSize++;shiftUp(usedSize-1);}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 usedSize==elem.length;}/*** 堆的删除:每次删除的都是优先级高的元素* 仍然要保持是大根堆*/public int poll() {if(isEmpty()){return -1;}int tmp=elem[0];swap(0,usedSize-1);usedSize--;shiftDown(0,usedSize);return tmp;}public boolean isEmpty() {return usedSize==0;}/*** 获取堆顶元素* @return*/public int peek (){return elem[0];}
}


http://www.ppmy.cn/ops/42702.html

相关文章

【MySQL精通之路】InnoDB-标准监视器和锁监视器

锁定监视器与标准监视器相同&#xff0c;只是它包含额外的锁信息。 为周期性输出启用任一监视器会打开相同的输出流&#xff0c;但如果启用了锁监视器&#xff0c;则该流会包含额外信息。 例如&#xff1a; 如果启用“标准监视器”和“锁定监视器”&#xff0c;则会打开单个…

【AI大模型】这可能是最简单的本地大模型工具,无须部署,一键使用

目录 前言 LM-Studio​编辑 那么问题来了&#xff0c;为什么我要在本地部署大模型&#xff1f; 隐私性&#xff1a; 定制性&#xff1a; 成本和体验的优化&#xff1a; 工具功能特点和使用方式介绍&#xff1a; 首页提供搜索功能和一些模型的推荐 模型下载管理&#x…

面试准备-项目【面试准备】

面试准备-项目【面试准备】 前言面试准备自我介绍&#xff1a;项目介绍&#xff1a; 论坛项目功能总结简介数据库表设计注册功能登录功能显示登录信息功能发布帖子评论私信点赞功能关注功能通知搜索网站数据统计热帖排行缓存 论坛项目技术总结Http的无状态cookie和session的区别…

LVS精益价值管理系统 LVS.Web.ashx SQL注入漏洞复现

0x01 产品简介 LVS精益价值管理系统是杭州吉拉科技有限公司研发的一款专注于企业精益化管理和价值流优化的解决方案。该系统通过集成先进的数据分析工具、可视化的价值流映射技术和灵活的流程改善机制,帮助企业实现高效、低耗、高质量的生产和服务。 0x02 漏洞概述 LVS精益…

SpringMVC流程

1、SpringMVC常用组件&#xff1a; DispatcherServlet&#xff08;请求分发器&#xff09;&#xff1a;Spring MVC的核心组件之一&#xff0c;负责处理全局配置和将用户请求分发给其他组件进行处理。Controller&#xff08;处理器&#xff09;&#xff1a; 实际处理业务逻辑的…

talib 安装

这里写自定义目录标题 talib 安装出错 talib 安装出错 https://github.com/cgohlke/talib-build/releases 这里找到轮子 直接装。

15分钟Element-UI快速入门

Element-UI 是一个基于 Vue.js 2.0 的桌面端组件库&#xff0c;它提供了丰富的、可复用的组件&#xff0c;帮助开发者快速构建出美观且功能强大的网页应用。以下是一个 Element-UI 的快速入门指南&#xff1a; 1. 安装 Element-UI 首先&#xff0c;你需要在你的 Vue.js 项目中…

【活动】开源与闭源大模型:探索未来趋势的双轨道路

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 开源与闭源大模型&#xff1a;探索未来趋势的双轨道路引言一、开源大模型&#…