优先级队列 (堆)

目录

一,堆的概念

二, 堆的存储结构

三, 堆的实现

3.1 shiftDown()

3.2 shiftUp()

3.3 shiftDown 与 shiftUp 的时间复杂度

四,堆排序


一,堆的概念

堆常用于实现优先队列(Priority Queue)等应用,其中可以快速查找和删除具有最大(或最小)优先级的元素。堆的操作包括插入新元素、移除堆中的顶部元素(即最值),以及对现有堆进行调整以满足堆序属性。常见的堆调整操作是"上浮"(上滤)和"下沉"(下滤)

堆具有以下两个主要特点:

  1.  堆是一个完全二叉树
  2.  堆中的每个节点的值都要大于等于(或小于等于)其子节点的值。

二, 堆的存储结构

从堆的概念可知,堆在逻辑结构上是一棵完全二叉树,因此可以层序的规则采用顺序的方式来高效存储,也就是说,堆是使用顺序表来存储的,画个图理解一下:

 将元素存储到数组中后,可以根据完全二叉树的性质对树进行还原。假设i为节点在数组中的下标,则有:

  • 如果i = 0,则 i 表示的节点为根节点,否则 i 节点的双亲节点为 (i - 1)/2
  • 如果2 * i + 1 小于节点个数,则节点 i 的左孩子下标为2 * i + 1,否则没有左孩子
  • 如果2 * i + 2 小于节点个数,则节点 i 的右孩子下标为2 * i + 2,否则没有右孩子

三, 堆的实现

在此实现的是大根堆:

public class Heap {
    private int[] elem;
    private int usedSize;

    public Heap(int[] arr){
        elem = new int[arr.length];
        createHeap(arr);
    }

    //建堆
    public void createHeap(int[] arr){
        for (int i = 0; i < arr.length; i++) {
            elem[i] = arr[i];
            usedSize++;
        }
        for (int parent = (usedSize-2)/2; parent >= 0; parent--) {
            shiftDown(parent,usedSize);
        }
    }

    //向下调整
    public void shiftDown(int parent, int len){}

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

    //入堆
    public void push(int val){}

    public boolean isFull(){
        return usedSize == elem.length;
    }

    //向上调整
    public void shiftUp(int child){}

    //出堆顶元素
    public int poll(){
        if(isEmpty()){
            System.out.println("堆中没有元素");
            return -1;
        }
        swap(0,usedSize-1);//将头尾交换
        usedSize--;//去掉堆顶元素
        shiftDown(0,usedSize);//重新排序
        return elem[usedSize];//返回堆顶元素
    }

    public boolean isEmpty(){
        return usedSize == 0;
    }

    //得到堆顶元素
    public int peek(){
        if(!isEmpty()){
            return elem[0];
        }
        System.out.println("堆中没有元素");
        return -1;
    }
}

堆中最核心的代码就是 shiftDown() 和 shiftUp() 方法的实现,其他的方法看看就懂了,下面来详细讲一讲这两个方法的实现

3.1 shiftDown()

比如说我们要将{27,15,19,18,28,34,65,49,25,37}这个数组变成一个堆,我们要如何实现,思路:先找到最后一棵子树,将它变成堆后,依次遍历其他的子树,直到最后一棵子树的根节点是整棵树的根节点结束,看下图: 

代码如下:

    public void shiftDown(int parent, int len){
        int child = 2*parent + 1;
        while(child < len){
            if(child+1 < len && elem[child] < elem[child+1]){
                child++;
            }
            if(elem[parent] < elem[child]){
                swap(parent,child);
                parent = child;
                child = 2*parent + 1;
            }else{
                break;
            }
        }
    }

3.2 shiftUp()

该方法是在插入一个元素时,将其以堆的形式插入,本质上shiftDown 与 shiftUp 的思路差不多:

 

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

3.3 shiftDown 与 shiftUp 的时间复杂度

 ​​​​​​​

四,堆排序

比如我们要进行升序排序,我们先要建立一个大根堆,再将根节点与最后一个节点交换,这个时候最后一个节点一定是的最大的,然后进行shiftDown,再将根节点与倒数第二个节点交换,依次类推。代码如下:

/**
     * 堆排序
     * 时间复杂度:O(N*logN)
     * 空间复杂度:O(1)
     * 不稳定
     */
    public void heapSort(int[] arr){
        createHeap(arr);
        int end = arr.length-1;
        while(end > 0){
            swap(arr,0,end);
            shiftDown(arr,0,end);
            end--;
        }
    }
    private void shiftDown(int[] arr, int parent,int len) {
        int child = 2*parent+1;
        while(child < len){
            if(child+1 < len && arr[child] < arr[child+1]){
                child++;
            }
            if(arr[child] > arr[parent]){
                swap(arr,child,parent);
                parent = child;
                child = 2*parent+1;
            }else{
                break;
            }
        }
    }
    public void swap(int[] arr, int i, int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
    public void createHeap(int[] array) {
        for (int parent = (array.length-2)/2; parent >= 0; parent--) {
            shiftDown(array,parent,array.length);
        }
    }

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

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

相关文章

偶数科技与白鲸开源完成兼容性认证

近日&#xff0c;偶数科技自主研发的云原生分布式数据库 OushuDB v5.0 完成了与白鲸开源集成调度工具 WhaleStudio v2.0 的兼容性相互认证测试。 测试结果显示&#xff0c;双方产品相互良好兼容&#xff0c;稳定运行、安全&#xff0c;同时可以满足性能需求&#xff0c;为企业级…

git从主仓库同步到fork仓库

git从主仓库同步到fork仓库 1. fork远程仓库到本地仓库2. 将远程仓库添加到本地3. 更新本地项目主库地址4. 将远程仓库更新到本地仓库5. 将本地仓库合到远程分支 1. fork远程仓库到本地仓库 方式一&#xff1a;通过git命令 git clone fork库地址方式二&#xff1a;通过git页面…

【100天精通python】Day22:字符串常用操作大全

目录 专栏导读 一、 字符串常用操作 1 拼接字符串 2 计算字符串长度 3 截取字符串 4 分割合并字符串 5 检索字符串 6 字母的大小写转换 7 去除字符串的空格和特殊字符 8 格式化字符串 二 、字符串编码转换 2.1 使用encode()方法编码 2.2 使用decoder()方法编码 专栏…

mysql的json处理

写在前面 需要注意&#xff0c;5.7以上版本才支持&#xff0c;但如果是生产环境需要使用的话&#xff0c;尽量使用8.0版本&#xff0c;因为8.0版本对json处理做了比较大的性能优化。你你可以使用select version();来查看版本信息。 本文看下MySQL的json处理。在正式开始让我们先…

HarmonyOS 开发基础(四) 子父组件双向绑定

一、知识点在代码注释里 index.ets // 导出方式直接从文件夹 import MyInput from "../common/commons/myInput" Entry Component /* 组件可以基于struct实现&#xff0c;组件不能有继承关系&#xff0c;struct可以比class更加快速的创建和销毁。*/ struct Index {…

【hive】Install hive using mysql as hive metadata service

文章目录 一. Requirements二. Installing Hive from a Stable Release三. Running Hive四. Running Hive CLI五.Running HiveServer2 and Beeline1. 下载安装mysql2. 下载mysql驱动3. 配置hive-site.xml4. 初始化元数据库5. 通过beeline进行连接 一. Requirements Users are s…

BES 平台 SDK之LED的配置

本文章是基于BES2700 芯片&#xff0c;其他BESxxx 芯片可做参考&#xff0c;如有不当之处&#xff0c;欢迎评论区留言指出。仅供参考学习用&#xff01; BES 平台 SDK之代码架构讲解二_谢文浩的博客-CSDN博客 关于SDK 系统框架简介可参考上一篇文章。链接如上所示&#xff01…

防火墙监控工具

防火墙监控是跟踪在高效防火墙性能中起着关键作用的重要防火墙指标&#xff0c;防火墙监控通常应包括&#xff1a; 防火墙日志监控防火墙规则监控防火墙配置监控防火墙警报监控 防火墙监控服务的一个重要方面是它应该是主动的。主动识别内部和外部安全威胁有助于在早期阶段识…

Devops系统中jira平台迁移

需求:把aws中的devops系统迁移到华为云中,其中主要是jira系统中的数据迁移,主要方法为在华为云中建立一套 与aws相同的devops平台,再把数据库和文件系统中的数据迁移,最后进行测试。 主要涉及到的服务集群CCE、数据库mysql、弹性文件服务SFS、数据复制DRS、弹性负载均衡ELB。 迁…

你知道HTTP与HTTPS有什么区别吗?

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、什么是HTTP&#xff1f; 二、什么是HTTPS&#xff1f; 三、HTTPS 的工作原理 1、客户端发起 HTTPS 请求 2、服务端的配置 3、…

2023年第四届“华数杯”数学建模思路 - 案例:异常检测

文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常检测 异常…

Arcgis 分区统计majority参数统计问题

利用Arcgis 进行分区统计时&#xff0c;需要统计不同矢量区域中栅格数据的众数&#xff08;majority&#xff09;&#xff0c;出现无法统计majority参数问题解决 解决&#xff1a;利用copy raster工具&#xff0c;将原始栅格数据 64bit转为16bit

大数据课程E1——Flume的概述

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解Ganglia的概念&#xff1b; ⚪ 了解Ganglia的拓扑结构和执行流程&#xff1b; ⚪ 掌握Ganglia的安装操作&#xff1b; 一、简介 1. 概述 1. Flume原本是由Cloude…

MySQL处理客户端请求

文章目录 一、连接管理二、解析与优化1、查询缓存2、语法解析3、查询优化 简单来说 MySQL 主要分为 Server 层和存储引擎层&#xff1a; Server 层&#xff1a;主要包括连接器、查询缓存、分析器、优化器、执行器等&#xff0c;所有跨存储引擎的功能都在这一层实现&#xff0c…

吃透《西瓜书》第四章 决策树定义与构造、ID3决策树、C4.5决策树、CART决策树

目录 一、基本概念 1.1 什么是信息熵&#xff1f; 1.2 决策树的定义与构造 二、决策树算法 2.1 ID3 决策树 2.2 C4.5 决策树 2.3 CART 决策树 一、基本概念 1.1 什么是信息熵&#xff1f; 信息熵: 熵是度量样本集合纯度最常用的一种指标&#xff0c;代表一个系统中蕴…

Android性能优化—ANR问题分析

一、ANR是什么&#xff1f; ANR(Application Not responding)&#xff0c;是指应用程序未响应&#xff0c;Android系统对于一些事件需要在一定的时间范围内完成&#xff0c;如果超过预定时间能未能得到有效响应或者响应时间过长&#xff0c;都会造成ANR。可以简单的理解为应用…

想写几个上位机,是选择学c#还是 c++ qt呢?

C#基本也就上位机开发开发&#xff0c;另外做做日常用的小工具很方便。 结合PLC&#xff0c;以太网做上位机&#xff0c;这个基本上控制这块都比较有需求。 另外我们用C#也做一些工具的二次开发&#xff0c;感觉还行。 C用qt框架其实学习起来可能稍微复杂些&#xff0c;但是…

Vue引入

1. vue引入 第一种方法&#xff1a;在线引入 <script src"https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 第二种方法&#xff1a;本地引入 2. 语法学习 el用于绑定id&#xff0c;data用于定义数据如下例题 <!DOCTYPE html> <html…

springboot基础--springboot配置说明

一、springboot中的配置文件 1、springboot为什么还需要用配置文件 方便我们修改springboot默认的配置;我们有其他的信息需要保存在配置文件中; 2、springboot中的配置文件有哪些 properties配置文件;yml配置文件; 3、springboot中的配置文件使用中注意事项 文件放入在sr…

数据中台系列2:rabbitMQ 安装使用之 window 篇

RabbitMQ 是一个开源的消息队列系统&#xff0c;是高级消息队列协议&#xff08;AMQP&#xff09;的标准实现&#xff0c;用 erlang 语言开发。 因此安装 RabbitMQ 之前要先安装好 erlang。 1、安装 erlang 到 这里 下载本机能运行的最新版 erlang 安装包。如果本机没有装过 …