【数据结构】堆,优先级队列

news2024/9/20 18:41:21

目录

  • 堆的性质
  • 大根堆的模拟实现
    • 接口实现
    • 构造方法
    • 建堆
    • 入堆
    • 判满
    • 删除
    • 判空
    • 获取堆顶元素
  • Java中的PriorityQueue
    • 实现的接口
    • 构造方法
    • 常用方法
    • PriorityQueue注意事项
  • 练习

如果有一个集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为 小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

堆的性质

  • 堆逻辑结构上是一棵完全二叉树。
  • 堆上的节点一定不大于(大根堆)或者不小于(小根堆)父亲节点。

大根堆的模拟实现

使用代码来实现一个大根堆。

接口实现

接口成员方法。

public class PriorityQueue {
    public int[] elem;
    public int usedSize;
    public PriorityQueue() {}
    //建堆
    public void createHeap(int[] array) {}
    /**
     * @param root 是每棵子树的根节点的下标
     * @param len  是每棵子树调整结束的结束条件
     * 向下调整的时间复杂度:O(logn)
     */
    private void shiftDown(int root,int len) {}
    // 入堆:仍然要保持是大根堆
    public void push(int val) {}
    private void shiftUp(int child) {}
    //判断堆是否满
    public boolean isFull() {}
    //每次删除的都是优先级高的元素,删除后任是大根堆
    public void pollHeap() {}
    //判断堆是否为空
    public boolean isEmpty() {}
     // 获取堆顶元素
    public int peekHeap() {}
}

构造方法

在构造方法中构建为长度10的数组。

public PriorityQueue() {
        elem = new int[10];
    }

建堆

createHeap思路:

  1. 先将数组拷贝进成员数组中(注意看长度是否够)。
  2. 我们从最后一棵子树的根节点开始调用shiftDown方法向上一棵一棵树的调整为大根堆。

shiftDown思路:

  1. 将当前传入的根节点与他的孩子节点将最大值选出作为根。
  2. 然后将根变成孩子节点再次调整。
  3. 注意挑选最大值的时候要判断不能让下标越界。
 public void createHeap(int[] array) {
        if(elem.length < array.length){
            elem = Arrays.copyOf(elem, elem.length * 2);
        }
        for (int i = 0; i < array.length; i++){
            elem[i] = array[i];
            usedSize++;
        }
        for (int root = (usedSize -1 -1) / 2; root >= 0 ; root--) {
            shiftDown(root,usedSize);
        }
    }

    /**
     * @param root 是每棵子树的根节点的下标
     * @param len  是每棵子树调整结束的结束条件
     * 向下调整的时间复杂度:O(logn)
     */
    private void shiftDown(int root,int len) {
        int child = root * 2 + 1;
        while (child < len){
            //寻找孩子节点的大值
            if(child + 1 < len && elem[child] < elem[child + 1]){
                child++;
            }
            if(elem[root] < elem[child]){
                swap(elem,root,child);
                root = child;
                child = root * 2 + 1;
            }else {
                break;
            }
        }
    }
    //交换函数
    private void swap(int[] array,int x,int y){
        int tmp = array[x];
        array[x] = array[y];
        array[y] = tmp;
    }

入堆

代码思路:

  1. 先判断堆是否已经满了,满了要扩容。
  2. 在堆最后存入该元素,然后与父亲节点相比较,比父亲节点大就交换,直到到根节点或者比父亲节点小为止。
	 /**
     * 入堆:仍然要保持是大根堆
     * @param val
     */
    public void push(int val) {
        if(isFull()){
            elem = Arrays.copyOf(elem, elem.length*2);
        }
        elem[usedSize] = val;
        shiftUp(usedSize);
        usedSize++;
    }
    private void shiftUp(int child) {
        int parent = (child - 1) / 2;
        while(parent >= 0) {
            if (elem[parent] < elem[child]) {
                swap(elem, parent, child);
                child = parent;
                parent = (child - 1) / 2;
            }else {
                break;
            }
        }
    }

判满

这个方法直接使用成员变量usedSize和数组长度判断即可。

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

删除

代码思路:

  1. 先判断堆是否为空,为空直抛空指针异常。
  2. 我们先将堆顶和堆尾交换,然后向下调整一次。
  3. useds减1。
ublic void pollHeap() throws NullPointerException {
        if (isEmpty()) {
            throw new NullPointerException();
        }
        swap(elem,0,usedSize-1);
        shiftDown(0,usedSize);
        usedSize--;
    }

判空

这个方法直接使用成员变量usedSize是否为0就行。

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

获取堆顶元素

如果堆为空,抛空指针异常,没有直接返回堆顶元素。

public int peekHeap() throws NullPointerException {
        if (isEmpty()) {
            throw new NullPointerException();
        }
        return elem[0];
    }

Java中的PriorityQueue

在Java中使用集合类PriorityQueue来表示优先级队列,其底层是一个小根堆。

实现的接口

构造方法

提供了以下3种构造方法:

方法方法用途介绍
PriorityQueue()创建一个空的优先级队列,默认容量是11
PriorityQueue(int initialCapacity)创建一个初始容量为initialCapacity的优先级队列,注意initialCapacity不能小于1,否则会抛IllegalArgumentException异常
PriorityQueue(Collection<? extends E> c)用一个集合来创建优先级队列

常用方法

常用方法如下:

PriorityQueue注意事项

  1. 使用要导包import java.util.PriorityQueue;
  2. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出ClassCastException异常。
  3. 不能插入null对象,否则会抛出NullPointerException
  4. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容。
  5. 如果要将PriorityQueue变成一个大根堆,类实现Comparator后重写 compare方法时将比较改为
public int compare(Integer o1, Integer o2) {
        return o2.compareTo(o1);
    }

练习

最小k个数

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

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

相关文章

Listen(sockfd,backlog)监听函数的第二个参数到底是什么?深度解释

listen队列剖析 int listen(int sockfd,int backlog) backlog : 监听套接字队列 对于一个调用监听的套接字&#xff0c;系统会维护给这个套接字两个队列 1. 未完成连接队列 //当客户端发生三次握手的第一次syn包给服务器的时候&#xff0c;服务器就会再未完成队列中创建…

数据库处理表

首先先创建库&#xff0c;然后创建需要的这三个表 用dese表名查看 然后题目要求对表进行修改 用alter table这个语法来对表进行修改 modify为修改字段 需要修改的字段的属性类型改变为的属性 最后用descStudent查看 第二题需要创建索引 创建索引createindex索引名称 cre…

世界启动Ⅷ--AI视频制作-方案与创新

1.文本/图片生成视频顾名思义&#xff0c;就是输入一段文本描述/上传一张图片即可生成对应的视频。我们常见的Runway、Pika、NeverEnds、Pixverse、svd等都属于此类。比如runway的影视风格Pika的动漫风格NeverEnds的人像模特当然还有一些外延应用&#xff0c;例如最近比较火的阿…

C++客户端Qt开发——Qt窗口(工具栏)

2.工具栏 使用QToolBar表示工具栏对象&#xff0c;一个窗口可以有多个工具栏&#xff0c;也可以没有&#xff0c;工具栏往往也可以手动移动位置 ①设置工具栏 #include "mainwindow.h" #include "ui_mainwindow.h" #include<QToolBar> #include<…

JavaSE--基础语法--继承和多态(第三期)

一.继承 1.1我们为什么需要继承? 首先&#xff0c;Java中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&#xff0c;但是 现实世界错综复杂&#xff0c;事物之间可能会存在一些关联&#xff0c;那在设计程…

开发AI自动直播工具需要了解的源代码!

随着人工智能技术的快速发展&#xff0c;AI自动直播工具成为了现代直播领域的一大创新&#xff0c;这些工具利用先进的算法和机器学习模型&#xff0c;能够自动化地生成、编辑和播出直播内容&#xff0c;极大地提高了直播的效率和质量。 然而&#xff0c;要开发一款功能强大的…

10 个顶级的PPT生成AI工具盘点,一文把所有好用软件尽收囊中!

你是否希望在工作中制作 PPT 演示文稿&#xff0c;与他人分享你的洞见&#xff0c;或是发表演讲&#xff1f;然而&#xff0c;使用传统的 PPT 制作方式既耗时又费力&#xff0c;步入 AI 时代后&#xff0c;人们寻求更智能、更简便的 PPT 演示文稿制作方法。 目前市场上出现了一…

谷粒商城实战笔记-65-商品服务-API-品牌管理-表单校验自定义校验器

文章目录 1&#xff0c;el-form品牌logo图片自定义显示2&#xff0c;重新导入和注册element-ui组件3&#xff0c;修改brand-add-or-update.vue控件的表单校验规则firstLetter 校验规则sort 校验规则 1&#xff0c;el-form品牌logo图片自定义显示 为了在品牌列表中自定义显示品…

本地部署VMware ESXi服务实现无公网IP远程访问管理服务器

文章目录 前言1. 下载安装ESXi2. 安装Cpolar工具3. 配置ESXi公网地址4. 远程访问ESXi5. 固定ESXi公网地址 前言 在虚拟化技术日益成熟的今天&#xff0c;VMware ESXi以其卓越的性能和稳定性&#xff0c;成为了众多企业构建虚拟化环境的首选。然而&#xff0c;随着远程办公和跨…

Codeforces Round 955 (Div. 2, with prizes from NEAR!) B. Collatz Conjecture(数学)

这道题考察的主要是通过数学对过程进行优化&#xff0c;而不是通过数学而得到结论&#xff08;让人摸不着头脑&#xff09;。 我们不需要把k次直接一次次的加&#xff0c;这样时间复杂度太大&#xff0c;那么我们现在探讨一次要加多少。 我们想要实现加一个数n&#xff0c;满足…

事务、函数和索引

什么是事务&#xff1f; 事务&#xff08;Transaction&#xff09;&#xff0c;就是将一组SQL语句放在同一批次内去执行&#xff0c;如果一个SQL语句出错&#xff0c;则该批次内 的所有SQL都将被取消执行。 特点 一个事务中如果有一个数据库操作失败&#xff0c;那么整个事务…

Linux网络-pingtelnet

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注我&#xff0c;我尽量把自己会的都分享给大家&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux服务器作为一个常用的网络服务器&#xff0c;主要的作用就是向客户端提供网络…

vue3前端开发-小兔鲜项目-关于详情页图片渲染的一些技术

vue3前端开发-小兔鲜项目-关于详情页图片渲染的一些技术&#xff01;经过前面几天的努力&#xff0c;我们现在已经可以正常渲染产品详情了。是时候汇总一下&#xff0c;基础的技术知识点了。 1&#xff1a;单页面组件内的抽离&#xff0c;是一种很重要的思想。当我们遇到了&…

leetcode日记(49)旋转链表

其实不难&#xff0c;就是根据kk%len判断需要旋转的位置&#xff0c;再将后半段接在前半段前面就行。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : …

World of Warcraft [CLASSIC] Timebadge

游戏币【每个服务器实时金价不一样&#xff0c;本例子是5000-6000金】 1枚【魔兽世界时光徽章】 30天游戏时间。 5760金币游戏币&#xff0c;策划如何消耗游戏里面的金币总量&#xff0c;以及如何留住那些非人民币玩家呢 30天加上去了 World of Warcraft [CLASSIC] [魔兽世界…

VitePress Index.md 的设置:开发者指南

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

使用vcpkg

概述 vcpkg 是 Microsoft 和 C 社区维护的免费开放源代码 C/C 包管理器。 它于 2016 年推出&#xff0c;可帮助开发人员将项目迁移到较新版本的 Visual Studio。 vcpkg 已演变成 Windows、macOS 和 Linux 上开发人员使用的跨平台工具。 vcpkg 拥有大量开放源代码库注册表和企业…

Linux-安装VMware-01

一、认识linux Linux 是一个开源的类 Unix 操作系统&#xff0c;由林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;于1991年首次发布。Linux 是许多计算机硬件的底层操作系统&#xff0c;特别是服务器、嵌入式系统和个人电脑。它支持多种架构&#xff0c;包括 x86、x64、A…

linux编译gcc源码详解

linux编译gcc源码详解 一、下载依赖包二、安装依赖2.1 安装m42.2 编译GMP2.3 编译MPFR2.4. 编译MPC2.5 设置环境变量三、gcc编译3.1 下载gcc3.2 编译gcc源码3.3 环境变量的配置一、下载依赖包 https://gcc.gnu.org/pub/gcc/infrastructure 命令下载依赖库,注意gcc编译时的依…

stm32cubeIDE与stm32cubeMX库文件安装路径自定义设置

1、 stm32cubeMX库文件安装路径自定义设置 打开stm32cubeMX软件&#xff0c;依次点击标题栏【Help】→【Updater Settings】 点击图中的【Browser】&#xff0c;选择自己想要存放库文件的文件夹&#xff0c;选择完成后点击【OK】即可设置成功。 PS&#xff1a;这里的路径建议…