优先级队列(堆)的实现

news2024/9/8 22:54:19

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

 

   /**
     *
     * @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)建堆 

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

 

3)堆的插入

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

 

 /**
     * 堆的删除:每次删除的都是优先级高的元素
     * 仍然要保持是大根堆
     */
    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.  对堆顶元素进行向下调整

 

    /**
     * 堆的插入:仍然要保持是大根堆
     * @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;
            }
        }
    }

 

 全部代码: 

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.coloradmin.cn/o/1694260.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Atlas 200I DK A2安装MindSpore Ascend版本

一、参考资料 mindspore快速安装 二、重要说明 经过博主多次尝试多个版本&#xff0c;Atlas 200I DK A2无法安装MindSpore Ascend版本。 也有其他博主测试&#xff0c;也未尝成功&#xff0c;例如&#xff1a;【MindSpore易点通漫游世界】在Atlas 200I DK A2 (CANN6.2.RC2)…

【汽车之家注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

构建php环境

目录 php简介 官网php安装包 选择下载稳定版本 &#xff08;建议使用此版本&#xff0c;文章以此版本为例&#xff09; 安装php解析环境 准备工作 安装依赖 zlib-devel 和 libxml2-devel包。 安装扩展工具库 安装 libmcrypt 安装 mhash 安装mcrypt 安装php 选项含…

Java——简易图书管理系统

本文使用 Java 实现一个简易图书管理系统 一、思路 简易图书管理系统说白了其实就是 用户 与 图书 这两个对象之间的交互 书的属性有 书名 作者 类型 价格 借阅状态 而用户可以分为 普通用户 管理员 使用数组将书统一管理起来 用户对这个数组进行操作 普通用户可以进…

BUUCTF靶场[Web] [极客大挑战 2019]Havefun1、[HCTF 2018]WarmUp1、[ACTF2020 新生赛]Include

[web][极客大挑战 2019]Havefun1 考点&#xff1a;前端、GET传参 点开网址&#xff0c;发现是这个界面 点击界面没有回显&#xff0c;老规矩查看源代码&#xff0c;看到以下代码 代码主要意思为&#xff1a; 用get传参&#xff0c;将所传的参数给cat&#xff0c;如果catdog…

c++中的命名空间与缺省参数

一、命名空间 1、概念&#xff1a;在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存 在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化&#xff0c; 以避免命名冲突或…

【介绍下Pwn,什么是Pwn?】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

汽车R155法规中,汽车获取到的VTA证书,E后面的数字表示什么意思?

标签&#xff1a; 汽车R155法规中&#xff0c;汽车获取到的VTA证书&#xff0c;E后面的数字表示什么意思&#xff1f;&#xff1b; 汽车&#xff1b;VTA认证; 有些厂商汽车拿到的VTA证书上面写着E9&#xff0c; 有些厂商汽车拿到的VTA证书上面写着E5&#xff0c;E9与E5有什么差…

华为机考入门python3--(29)牛客29-字符串加解密

分类&#xff1a;字符变换 知识点&#xff1a; 字符是字母 char.isalpha() 字符是小写字母 char.islower() 字符是数字 char.isdigit() b变C chr((ord(b) - ord(a) 1) % 26 ord(A)) 题目来自【牛客】 # 加密 def encrypt_string(s):result ""for ch…

OWASP top10--SQL注入(一)

SQL注入式攻击技术&#xff0c;一般针对基于Web平台的应用程序.造成SQL注入攻击漏洞的原因&#xff0c;是由于程序员在编写Web程序时&#xff0c;没有对浏览器端提交的参数进行严格的过滤和判断。用户可以修改构造参数&#xff0c;提交SQL查询语句&#xff0c;并传递至服务器端…

【408精华知识】主存相关解题套路大揭秘!

讲完了Cache&#xff0c;再来讲讲主存是怎么考察的&#xff0c;我始终认为&#xff0c;一图胜千言&#xff0c;所以对于很多部件&#xff0c;我都是通过画图进行形象的记忆&#xff0c;那么接下来我们对主存也画个图&#xff0c;然后再来详细解读其考察套路~ 文章目录 零、主存…

Linux驱动学习之模块化,参数传递,符号导出

1.模块化 1.1.模块化的基本概念&#xff1a; 模块化是指将特定的功能或组件独立出来&#xff0c;以便于开发、测试和维护。在Linux设备驱动中&#xff0c;模块化允许将驱动程序作为内核模块动态加载到系统中&#xff0c;从而提高了系统的灵活性和可扩展性。 1.2.Linux内核模…

Kata Containers零基础学习从零到一

文章目录 docker和Kata Containers的区别Docker容器共享宿主机内核每个容器实例运行在轻量级虚拟机&#xff08;MicroVM&#xff09;总结 通俗例子Kata Containers架构实际Kata Containers架构图解容器技术栈总结 agent和shim家长&#xff08;shim进程&#xff09;的角色保姆&a…

OpenHarmony 实战开发——一文总结ACE代码框架

一、前言 ACE_Engine框架是OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&#xff09;的UI开发框架&#xff0c;为开发者提供在进行应用UI开发时所必需的各种组件&#xff0c;以及定义这些组件的属性、样式、事件及方法&#xff0c;通过这些组件可以方便进行OpenHarmo…

java基础-JVM日志、参数、内存结构、垃圾回收器

一、基础基础 1.1 数据类型 Java的数据类型分为原始数据类型和引用数据类型。 原始数据类型又分为数字型和布尔型。 数字型又有byte、short、int、long、char、float、double。注意&#xff0c;在这里char被定义为整数型&#xff0c;并且在规范中明确定义&#xff1a;byte、…

primeflex样式库笔记 Display相关的案例

回顾 宽度设置的基本总结 w-full&#xff1a;表示widtdh&#xff1a;100%&#xff1b;占满父容器的宽度。 w-screen&#xff1a;表示占满整个屏幕的宽度。 w-1到w-12&#xff0c;是按百分比划分宽度&#xff0c;数字越大&#xff0c;占据的比例就越大。 w-1rem到w-30rem&…

推特热帖:大语言模型自荐能够替代的20种人类工作!快来看你是否需要转行!

最近推特上有一个例子引起了广泛的讨论&#xff0c;事情的起因是这样的&#xff1a;网友让 GPT-4o 预测一下自己未来将会替代人类哪些工作&#xff1f; 这听起来很有趣&#xff01;GPT-4o会给出什么样的预测呢&#xff1f; 3.5研究测试&#xff1a;hujiaoai.cn 4研究测试&…

动物合并消除休闲游戏源码 Animal Merge 益智游戏

一款动物合并消除休闲游戏源码&#xff0c;Animal Merge是一款引人入胜的益智游戏&#xff0c;玩家的任务是合并方块&#xff0c;创造出可爱的动物&#xff0c;这些动物的体型会逐渐变大。游戏玩法包括将方块放到网格上&#xff0c;并战略性地将它们合并以形成更大的动物形状。…

数据库--数据库基础(一)

目录 第一章 绪论 一.数据库的基本概念 1. 数据库的4个基本概念 2、数据库系统的特点 二.数据库和文件 三.数据模型 1.概念模型 2.逻辑模型(物理模型) 2.1关系模型 四.数据库系统的三级模式结构&#xff1a; 五数据库的二级映像功能与数据独立性 第二章 关系数据库…

ffpmeg windows WSl 编译so

1.NDK 环境变量配置 2.git clone ffpmeg 3.创建脚本&#xff08;需先下载gcc编译器&#xff09; 64位脚本如下 #!/bin/bashexport NDK/home/test/ndk20 #这里配置先你的 NDK 路径 TOOLCHAIN$NDK/toolchains/llvm/prebuilt/linux-x86_64function build_android {./configure \ …