优先级队列(堆)的概念+模拟堆的实现

news2024/11/24 1:25:05

文章目录

  • 优先级队列(堆)的概念+模拟堆的实现
    • 一、概念
    • 1.优先级队列
    • 2.堆
      • 1.堆的性质
      • 2.堆的存储
      • 3.堆的创建
        • 3.1 向下调整
        • 3.2建堆的时间复杂度 O(N)
      • 4.堆的插入
        • 4.1向上调整
        • 4.2向上调整建堆的时间复杂度:O(N * log N)
      • 5.堆的删除


优先级队列(堆)的概念+模拟堆的实现


一、概念

1.优先级队列

优先级队列 Priority Queue

  • 队列中操作的数据带有优先级,出队的时候,优先级高的先出
  • 可以返回最高优先级对象,可以添加新的对象
  • 在Java1.8中,priorityQueue的底层使用了堆,堆的相当于对完全二叉树进行了调整

2.堆

  • 将一个关键码的集合中所以元素,按照完全二叉树的顺序,存进一个一维数组当中

1.堆的性质

1.堆中结点的值,总是不大于/不小于它父亲结点的值

2.堆总是一棵完全二叉树

在这里插入图片描述

2.堆的存储

  • 堆是一棵完全二叉树,层序的规则可以用顺序的方法来存储

  • 完全二叉树从上到下,从左往右依次排列,存进数组中没有空的位置

  • 结点在数组下标为i,其双亲结点为( i - 1 )/ 2

  • 左孩子:2 * i +1 ; 右孩子:2 * i + 2

3.堆的创建

3.1 向下调整

每棵树都向下调整,维护大根堆

  • 向下调整的时间复杂度:== 树的高度

  • 向下调整建堆的时间复杂度:O(n)

在这里插入图片描述

  • 每棵树从父结点向下走,要找到每棵树的父结点

  • 从最后一棵子树来进行调整,找到最后一个结点和它的双亲结点,遍历得到父结点的下标

  • 找到最大的子节点,比较后进行交换

public class TestHeap {
    public int[] elem;//底层是一个一维数组
    public int usedSize;//记录当前堆中有多少条数据

    public TestHeap() {
        this.elem = new int[10];
    }

    public void initElem(int[] array) {//初始化
        for (int i = 0; i < array.length; i++) {
            elem[i] = array[i];
            usedSize++;
        }
    }
}

1.进行初始化

    public void createHeap() {//堆的创建
        //最后一个结点的下标= usedSize-1,它的双亲结点的下标= (usedSize-1-1)/2
        for (int parent = (usedSize - 1 - 1) / 2; parent >= 0; parent--) {//求出parent
            shiftDown(parent, usedSize);//结束下标传usedSize
            //结束的结点下标的值不会超过usedSize
        }
    }

    /**
     * 父亲下标
     * 每棵树的结束下标
     *
     * @param parent
     * @param len
     */
    private void shiftDown(int parent, int len) {//向下调整,每棵树从父结点向下走
        int child = 2 * parent + 1;
        // child < len最起码要有一个左孩子
        while (child < len) {
            //child + 1保证一定有右孩子的情况下,和右孩子比较
            if (child + 1 < len && elem[child] < elem[child + 1]) {//右孩子大
                child++;
            }
            //保证child的下标是左右孩子最大值的下标
            if (elem[child] > elem[parent]) {//如果子节点的值比父结点的大,交换
                int tmp = elem[child];
                elem[child] = elem[parent];
                elem[parent] = tmp;

                parent = child;//交换完成后,让parent结点等于等于当前child结点,
                child = 2 * parent + 1;//重新求子节点的位置,再次进入循环交换

            } else {
                break;//比父结点小,结束循环
            }
        }
    }

堆的创建

1.遍历得到每个双亲结点,根据双亲结点找到子节点,保证child的下标是左右孩子最大值的下标

2.子节点和父结点比较并交换

3.2建堆的时间复杂度 O(N)

向下调整的方式建立大根堆、小根堆,时间复杂度约等于O(n)

在这里插入图片描述

用满二叉树来分析

4.堆的插入

    public void offer(int val) {
        if (isFull()) {//如果满了就扩容
            elem = Arrays.copyOf(elem, 2 * elem.length);
        }
        elem[usedSize++] = val;//存到最后
        //进行向上调整
        shiftUp(usedSize - 1);//传进孩子结点的下标

    }

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

    private void shiftUp(int child) {//向上调整,已知孩子结点的下标求父亲结点的下标
        int parent = (child - 1) / 2;
        while (child > 0) {//循环结束的条件就是child =0
            if (elem[child] > elem[parent]) {//比较、交换
                int tmp = elem[child];
                elem[child] = elem[parent];
                elem[parent] = tmp;
                child = parent;
                parent = (child - 1) / 2;
            } else {
                break;
            }
        }
    }
4.1向上调整
  • 插入到有效数据的最后,空间不够要扩容,成为新的子节点,已知孩子结点,求父亲结点
  • 向上调整,调整的过程中,直接和父结点比较,如果比父结点的值大就交换
  • 不用比较左右孩子的最大值,因为根节点的子树本身就是大根堆,不用进行维护
4.2向上调整建堆的时间复杂度:O(N * log N)

在这里插入图片描述

5.堆的删除

  • 1.堆的删除,删除的是堆顶元素
  • 2.将0下标和最后一个元素的下标进行交换,将堆中有效数据个数减少一个
  • 3.对堆顶元素进行向下调整,只需要调整0下标的数
    /**
     * 删除堆顶
     */
    public void pop() {
        if (isEmpty()) {
            return;
        }
        swap(elem, 0, usedSize - 1);//堆顶和最后一个元素交换
        usedSize--;//删除一个元素
        shiftDown(0, usedSize);//向下调整
    }

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

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

    public int peek() {
        if (isEmpty()) {
            return -1;
        }
        return elem[0];
    }

点击移步博客主页,欢迎光临~

偷cyk的图

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

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

相关文章

【Java 进阶篇】Java Session 原理及快速入门

大家好&#xff0c;欢迎来到本篇博客。今天&#xff0c;我们将探讨Java Web开发中一个重要而令人兴奋的概念&#xff0c;即Session&#xff08;会话&#xff09;。Session是一种在Web应用程序中跟踪用户状态和数据的机制。我们将深入了解Session的原理&#xff0c;并通过示例来…

LangChain+LLM实战---LlamaIndex、正确使用索引

LlamaIndex简介 LlamaIndex(也称为GPT Index)是一个用户友好的界面&#xff0c;它将您的外部数据连接到大型语言模型(Large Language Models, llm)。它提供了一系列工具来简化流程&#xff0c;包括可以与各种现有数据源和格式(如api、pdf、文档和SQL)集成的数据连接器。此外&a…

Android Studio(对话框AlertDialog)

前言 前面介绍了常用控件的相关属性&#xff0c;那些控件的使用起来也很容易。在本节及后面的章节介绍的控件将是相比于前面使用起来较为复杂的&#xff08;不过使用多了&#xff0c;也很容易上手&#xff09;。 这些控件常常需要配合java代码来使用&#xff0c;比如说对话框、…

如何将PDF文件转换成翻页电子书?这个网站告诉你

​随着电子书的普及&#xff0c;越来越多的人开始将PDF文件转换成翻页电子书。翻页电子书不仅方便阅读&#xff0c;而且还可以在手机上轻松翻页。那么如何将PDF文件转换成翻页电子书呢&#xff1f;今天就为大家介绍一个网站&#xff0c;可以帮助你轻松完成这个任务。 1.首先&am…

Redis-使用java代码操作Redis->java连接上redis,java操作redis的常见类型数据存储,redis中的项目应用

java连接上redisjava操作redis的常见类型数据存储redis中的项目应用 1.java连接上redis package com.zlj.ssm.redis;import redis.clients.jedis.Jedis;/*** author zlj* create 2023-11-03 19:27*/ public class Demo1 {public static void main(String[] args) { // …

语言的新启程之Solidity

官方网站 WTF-Solidity官网 编译器 区块链的基础 Gas 一经创建&#xff0c;每笔交易都收取一定数量的 gas&#xff0c;目的是限制执行交易所需要的工作量和为交易支付手续费。EVM 执行交易时&#xff0c;gas 将按特定规则逐渐耗尽。 gas price 是交易发送者设置的一个值&…

深入理解计算机系统CS213 - Lecture 02

Bits, Bytes, and Integer 1.位运算与条件运算 &&#xff0c;|&#xff0c;^&#xff0c;~ 是做位运算。诸位01运算。 &&&#xff0c;||&#xff0c;&#xff01;是判断条件真假&#xff0c;而后返回0或1。 2. 位移 x << y&#xff1a;左移y位&#xff…

Excel·VBA工作表导出为图片

《Excel转图片别再截图啦&#xff01;用这4个方法&#xff0c;高清且无损&#xff01;》&#xff0c;excel转为图片一般方法较为简单&#xff0c;那么能否使用vba将excel转为图片 选中区域导出为图片 zoom设置为2&#xff0c;导出图片较为清晰 Sub 选中区域导出为图片()Dim …

【iOS】——知乎日报第三周总结

文章目录 一、获取新闻额外信息二、工具栏按钮的布局三、评论区文字高度四、评论区长评论和短评论的数目显示五、评论区的cell布局问题和评论消息的判断 一、获取新闻额外信息 新闻额外信息的URL需要通过当前新闻的id来获取&#xff0c;所以我将所有的新闻放到一个数组中&…

MySQL基础『数据库基础』

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; MySQL 学习 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 &#x1f381;软件版本&#xff1a; MySQL 5.7.44 文章目录 1.数据库概念1.1.什么是数据库1.2.数据库存储介质1.3.常见数据库 2.数…

【带头学C++】----- 三、指针章 ---- 3.5 字符串与指针

在 C 中&#xff0c;字符串可以通过指针来表示和操作。C 的字符串是由字符组成的字符数组&#xff0c;而指针则用于引用和操作内存中的数据。 1. 字符数组 1. 字符数组: 字符数组是最基本的字符串表示方式。可以使用字符数组来存储字符串&#xff0c;并使用指针来引用它。字符…

嵌入式中利用VS Code 远程开发原理

VS Code几乎是所有的程序员必备的工具之一&#xff0c;据说全球一般的开发者都使用过VS Code这款工具。 今天分享一篇 VS Code 实现远程办公相关的文章。 1、概 述 通常&#xff0c;我们都是每天到工作的办公室进行办公&#xff0c;但是&#xff0c;如果下班回家&#x…

Linux学习第32天:Linux INPUT 子系统实验(一):接纳

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 题目中用了“接纳”俩字。其实学习就是一个接纳的过程。接纳新的知识&#xff0c;从而转化为自己知识宝库的一部分。那今天学习的input子系统和今天的主题接纳有…

0基础2小时搭建自己的网站

​作者主页 &#x1f4da;lovewold少个r博客主页 ⚠️本文重点&#xff1a;0基础2小时搭建个人网站 &#x1f449;【C-C入门系列专栏】&#xff1a;博客文章专栏传送门 &#x1f604;每日一言&#xff1a;宁静是一片强大而治愈的神奇海洋&#xff01; 目录 前言 第一步 环境…

DETR 论文精读【论文精读】End-to-End Object Detection with Transformers

DETR 这篇论文&#xff0c;大家为什么喜欢它&#xff1f;为什么大家说它是一个目标检测里的里程碑式的工作&#xff1f;而且为什么说它是一个全新的架构&#xff1f; 大家好&#xff0c;今天我们来讲一篇 ECC V20 的关于目标检测的论文。它的名字想必大家都不陌生&#xff0c;也…

系列十二、过滤器 vs 拦截器

一、过滤器 vs 拦截器 1.1、区别 &#xff08;1&#xff09;触发时机不一样&#xff0c;过滤器是在请求进入容器后Servlet之前进行预处理的&#xff0c;请求结束返回也是&#xff0c;是在Servlet处理完后&#xff0c;返回给前端之前&#xff1b; &#xff08;2&#xff09;过滤…

5.3有效的括号(LC20-E)

算法&#xff1a; 题目中&#xff1a;左括号必须以正确的顺序闭合。意思是&#xff0c;最后出现的左括号&#xff08;对应着栈中的最后一个元素&#xff09;&#xff0c;应该先找到对应的闭合符号&#xff08;右括号&#xff09; 比如:s"( [ ) ]"就是False&#xf…

个人服务器到期,项目下线,新的开始

告别旧服务器 2023.11.06服务器到期&#xff0c;所有项目正式下线 时间真的过的很快&#xff0c;从开始踏入编程的大门&#xff0c;到现在不知不觉已经陆续经手了两台服务器了&#xff0c;目前这台服务器是一年前的阿里云活动白嫖的嘿嘿嘿&#xff0c;该服务器上目前运行的项…

Docker与微服务实战——基础篇

Docker与微服务实战——基础篇 第一章 Docker 简介1.1 docker 理念1.2 容器与虚拟机比较 第二章 Docker 安装2.1 前提说明2.2 Docker的基本组成2.2.1 镜像&#xff08;image&#xff09;2.2.2 容器&#xff08;container&#xff09;2.2.3 仓库&#xff08;repository&#xff…

[MICROSAR Adaptive] --- Hello Adaptive World

Automotive E/E Architecture and AUTOSAR Adaptive Platform Vector Solution: MICROSAR Adaptive First project: Hello Adaptive World Summary 1 引言 1.1 AP诞生的历史背景 新一代电子电器架构通常将车内的节点分为三类。计算平台,预控制器和传感器执行器相关的节点,…