【优先级队列 之 堆的实现】

文章目录

  • 前言
  • 优先级队列 PriorityQueue
    • 优先队列的模拟实现
    • 堆的储存方式
    • 堆的创建
    • 建堆的时间复杂度
    • 堆的插入与删除
  • 总结


前言


优先级队列 PriorityQueue

概念:对列是先进先出的的数据结构,但有些情况,数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列。所以像这种情况用队列不太合适:在手机上玩游戏时,如果有来电,系统应该优先处理打进来的电话。以前是来电显示充满整个画面,现在变成了一个小窗。

优先队列的模拟实现

PriorityQueue的底层使用了堆这种数据结构(PriorityQueue底层实现是一个完全二叉树,完全二叉树又分为大根堆和小根堆)

概念:
小根堆:根节点比左右孩子都小。只考虑根和左右节点的关系,不考虑左右节点的哪个大。
大根堆:根节点比左右孩子都大

堆的储存方式

在这里插入图片描述
将元素存储到数组中后,可以根据二叉树章节的性质5对树进行还原。假设为节点在数组中的下标,则有: 如果为0,则表示的节点为根节点,否则节点的双亲节点为(i 1)/2
●如果2i+ 1小于节点个数,则节点的左孩子下标为2 门中1,否则没有左孩了
●如果2
i+2小于节点个数,则节点的右孩子下标为2
1+ 2,否则没有右孩子

堆的创建

  1. 让parent标记需要调整的节点,child标记parent的左孩子(注意: parent如果有孩子一 定先是有左孩子)
  2. 如果parent的左孩子存在,即:child < size,进行以下操作, 直到parent的左孩子不存在
    parent右孩子是否存在,存在找到左右孩子中最大的孩子,让child进行标记
  3. 将parent 与较大的孩子child比较,如果:
    parent小于较大的孩子child,交换parent与较大的孩子child,交换完成之后,parent中小的元素向下移动,并继续向下调整,即parent = child; child = parent*2+1;然后继续
    否则:退出循环。
public class TestHeap {
    //创建一个数组
    public int[] elem;
    public int useSize;//有效元素

    //构造方法给elem分配内存
    public TestHeap() {
        this.elem = new int[10];
    }

    //初始化elem数组,给elem传入元素
    public void initElem(int[] array){
        for (int i = 0; i < array.length; i++) {
            elem[i] = array[i];
            useSize++;
        }
    }

    /**
     * 创建大根堆的代码
     */
    public void createHeap(){
        for (int parent =(useSize-1-1)/2 ; parent >=0 ; parent--) {
            siftDown(parent,useSize);

        }
    }

    /**
     * 向下调整
     * @param parent
     * @param len
     */
     //让child标记根的左孩子,如果左孩子大于数组长度则进行下面操作
    // 如果右孩子小于长度并且左孩子的值小于右孩子的值,让左孩子移到右孩子上
    private void siftDown(int parent,int len){
        int child = 2*parent+1;
        while(child < len){
            if (child+1 < len && elem[child] < elem[child+1]){
                child = child+1;
            }
            //此时child保存的是孩子节点中最大的值
            //如果左孩子大于根节点,两者的值交换。
            if (elem[child] > elem[parent]) {
                //和根节点交换
                int tmp = elem[child];
                elem[child] = elem[parent];
                elem[parent] = tmp;
                //交换完再换位置
                parent = child;//根节点移到孩子节点上
                child = 2*parent+1;//孩子节点再往下移

            }else{
                break;
            }


        }
    }
}

public class Test {
    public static void main(String[] args) {
        TestHeap testHeap = new TestHeap();
        int[] array={27,15,19,18,28,34,65,49,25,37};
        testHeap.initElem(array);
        testHeap.createHeap();
        System.out.println("========");
    }
}

建堆的时间复杂度

在这里插入图片描述
因此:建堆的时间复杂度是0(N)

堆的插入与删除

堆的插入:
在这里插入图片描述

    private void swap(int i,int j){
        int tmp = elem[i];
        elem[i] = elem[j];
        elem[j] = tmp;
    }

    //向上调整
    public void push(int val){
        if(isFull()){
            elem = Arrays.copyOf(elem,elem.length*2);
        }
        elem[usedSize] = val;
        siftUp(usedSize);
        usedSize++;
    }
    public boolean isFull(){
        return usedSize == elem.length;
    }
    public void siftUp(int child){
        int parent = (child-1)/2;
        while(child > 0){
            if (elem[child] > parent){
                swap(child,parent);
                child = parent;
                parent = (child-1)/2;
            }else{
                break;
            }
        }
    }

堆的删除
注意:这里的删除指的是删除堆顶的元素

  1. 将0下标的的堆顶元素和堆的最后一个元素交换
  2. 将堆的有效个数usedSize–
  3. 对堆进行向下调整
    //删除堆顶元素
    public int pop(){
        if (empty()){
            return -1;
        }
        int oldVal = elem[0];
        swap(0,usedSize-1);
        usedSize--;
        siftDown(0,usedSize);
        return oldVal;
    }
    public boolean empty(){
        return usedSize == 0;
    }

总结

本章节学习如何实现一个堆,如何运用到向上调整,向下调整。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++:使用tinyXML生成矢量图svg

先说一下tinyXML库的配置&#xff1a; 很简单&#xff0c;去下面官网下载 TinyXML download | SourceForge.net 解压后是这样 直接将红框中的几个文件放到项目中即可使用 关于svg文件&#xff0c;SVG是基于XML的可扩展矢量图形&#xff0c;svg是xml文件&#xff0c;但是xml…

TCP三握四挥(面试需要)

TCP建立连接需要三次握手过程&#xff0c;关闭连接需要四次挥手过程 三次握手 从图中可以看出&#xff0c;客户端在发起connect时&#xff0c;会发起第一次和第三次握手。服务端在接收客户端连接时&#xff0c;会发起第二次握手。 这三次握手&#xff0c;都会通过SYNACK的方式…

阿里云4核8G云服务器价格、带宽及系统盘费用

阿里云服务器4核8g配置云服务器u1价格是955.58元一年&#xff0c;4核8G配置还可以选择ECS计算型c7实例、计算型c8i实例、计算平衡增强型c6e、ECS经济型e实例、AMD计算型c8a等机型等ECS实例规格&#xff0c;规格不同性能不同&#xff0c;价格也不同&#xff0c;阿里云服务器网al…

EasyExcel入门使用

EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。他能让你在不用考虑性能、内存的等因素的情况下&#xff0c;快速完成Excel的读、写等功能。 EasyExcel 的主要特点如下&#xff1a; 1、高性能&#xff1a;EasyExcel 采用了异步导入导出的方式&…

数据结构:搜索二叉树 | 红黑树 | 验证是否为红黑树

文章目录 1.红黑树的概述2.红黑树的性质3.红黑树的代码实现3.1.红黑树的节点定义3.2.红黑树的插入操作3.3.红黑树是否平衡 黑红树是一颗特殊的搜索二叉树&#xff0c;本文在前文的基础上&#xff0c;图解红黑树插入&#xff1a;前文 链接&#xff0c;完整对部分关键代码展示&a…

macOS跨进程通信: Unix Domain Socket 创建实例

macOS跨进程通信: Unix Domain Socket 创建实例 一&#xff1a; 简介 Socket 是 网络传输的抽象概念。 一般我们常用的有Tcp Socket和 UDP Scoket&#xff0c; 和类Unix 系统&#xff08;包括Mac&#xff09;独有的 Unix Domain Socket&#xff08;UDX&#xff09;。 Tcp So…

避雷!仅1天撤回55篇中国学者的研究论文!这本毕业神刊需要注意!

【SciencePub学术】 这本国际期刊&#xff0c;仅仅去年12月一个月的时间&#xff0c;就撤回了近60篇国人文章&#xff01;这本期刊就是来自Hindawi出版社的APPLIED BIONICS AND BIOMECHANICS。 01 期刊信息简介 APPLIED BIONICS AND BIOMECHANICS IF(2022)&#xff1a;2.2&…

三维城市模型提升日本的智慧城市管理

MicroStation 将工作效率提高 50%&#xff0c;实现了前所未有的逼真模拟 构建三维城市模型生态系统 PLATEAU 项目由日本国土交通省牵头&#xff0c;是一项三维城市模型和数字孪生计划&#xff0c;旨在到 2027 年为日本 500 个城市构建开放的城市模型数字生态系统。作为日本最…

java获取linux和window序列号

前言 获取系统序列号在Java中并不是一个直接支持的功能&#xff0c;因为Java语言本身并不提供直接访问硬件级别的信息&#xff0c;如CPU序列号。但是&#xff0c;我们可以使用一些平台特定的工具或命令来实现这一功能。下面我将展示如何使用Java获取Windows和Linux系统上的CPU…

通过代理服务器的方式解决跨域问题

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes 觉得有帮助的同学&#xff0c;可以点心心支持一下哈 这里以本地访问https://heimahr.itheima.net/api/sys/permission接口为列子 Node.js 代理服务器 (server.js) 本次考虑使用JSONP或CORS代理来…

PHP“引用”漏洞

今日例题&#xff1a; <?php highlight_file(__FILE__); error_reporting(0); include("flag.php"); class just4fun { var $enter; var $secret; } if (isset($_GET[pass])) { $pass $_GET[pass]; $passstr_replace(*,\*,$pass); } $o unser…

【操作系统】实验三 编译 Linux 内核

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

[Linux]HTTP状态响应码和示例

1xx&#xff1a;信息响应类&#xff0c;表示接收到请求并且继续处理 2xx&#xff1a;处理成功响应类&#xff0c;表示动作被成功接收、理解和接受 3xx&#xff1a;重定向响应类&#xff0c;为了完成指定的动作&#xff0c;必须接受进一步处理 4xx&#xff1a;客户端错误&#x…

如何使用Docker本地部署Jupyter Notebook并结合内网穿透实现远程访问

&#x1f4d1;前言 本文主要是Linux下通过使用Docker本地部署Jupyter Notebook并结合内网穿透实现远程访问的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;…

单调栈笔记

单调栈 1.每日温度2.下一个更大元素 I3.下一个更大的元素4.接雨水5.柱状图中最大的矩形 单调栈正如其名字&#xff0c;用一个栈&#xff08;能够实现栈性质的数据结构就行&#xff09;来存储元素&#xff0c;存储在栈中的元素保持单调性&#xff08;单调递增或者是单调递减&…

Allegro如何设置飞线的显示方式?

预拉线最短化。 设置方法:选择菜单栏Setup→Design Parameters...(参数设置) 跳出下面对话框,根据需求设置。 Jogged:拼合的。 Straight:直的。 Closest endpoint:最靠近端点。 Pin to pin:引脚到引脚。 Jogged的显示效果。

MyBatis的逆向工程的创建,generator插件的使用和可能出现的一些问题,生成的实体类多出.java 1 .java 2这种拓展文件的处理方案

目录 创建逆向工程的步骤 ①添加依赖和插件 ②创建MyBatis的核心配置文件 ③创建逆向工程的配置文件 ④执行MBG插件的generate目标 数据库版本8有可能出现的问题&#xff1a; 1、生成的实体类多了.java 1 .java 2的拓展文件... 2、生成的属性与表中字段不匹配&#xff…

【IEEE会议征稿】2024年第九届智能计算与信号处理国际学术会议(ICSP 2024)

2024年第九届智能计算与信号处理国际学术会议&#xff08;ICSP 2024&#xff09; 2024年第八届智能计算与信号处理国际学术会议&#xff08;ICSP 2024&#xff09;将在西安举行&#xff0c; 会期是2024年4月19-21日&#xff0c; 为期三天, 会议由西安科技大学主办。 欢迎参会&…

Linux 一键部署influxd2-telegraf

influxd2前言 influxd2 是 InfluxDB 2.x 版本的后台进程,是一个开源的时序数据库平台,用于存储、查询和可视化时间序列数据。它提供了一个强大的查询语言和 API,可以快速而轻松地处理大量的高性能时序数据。 telegraf 是一个开源的代理程序,它可以收集、处理和传输各种不…

全双工通信协议:WebSockets+STOMP

全双工通信协议&#xff1a;WebSocketsSTOMP 前言启动STOMPWebSocket传输消息流注释控制器发送消息代理点作为分隔符证明用户目的地消息的顺序事件拦截STOMP客户端表演监视测试案例一&#xff1a;发送指定用户消息 关联文章 前言 WebSocket协议定义了两种类型的消息(文本和二进…