最大堆 和 优先队列

2023-11-07

最大堆

MaxHeap.java

import java.util.Random;  // 后面测试用

public class MaxHeap<E extends Comparable<E>> {
    private Array<E> data;

    public MaxHeap(int capacity){
        data = new Array<>(capacity);
    }

    public MaxHeap(){
        data = new Array<>();
    }

    /**
     * 将数组转化为堆
     * 一开始就把数组当成未规范的堆,
     * 然后从第一个非叶子节点开始做sift down, 一直到根结点
     * @param arr
     */
    public MaxHeap(E[] arr){
        data = new Array<>(arr);
        for(int i=parent(arr.length-1); i>=0; i--){
            siftDown(i);
        }
    }

    public int size(){
        return data.getSize();
    }

    public boolean isEmpty(){
        return data.isEmpty();
    }

    /**
     *
     * @param index
     * @return 父节点的索引
     */
    private int parent(int index){
        if(index == 0)
            throw new IllegalArgumentException("No parent");
        return (index-1)/2;
    }

    /**
     *
     * @param index
     * @return 左孩子的索引
     */
    private int leftChild(int index){
        return index * 2 + 1;
    }

    /**
     *
     * @param index
     * @return 右孩子的索引
     */
    private int rightChild(int index){
        return index * 2 + 2;
    }

    /**
     * 添加元素e
     * 思路: 把元素添加到最后一个, 然后向上浮动形成最大堆
     * @param e
     */
    public void add(E e){
        data.addLast(e);
        siftUp(data.getSize() - 1);
    }

    /**
     * 向上浮动
     * @param k
     */
    private void siftUp(int k) {
        // 一直循环, 如果k有父节点, 且比父节点大
        while(k > 0 && data.get(parent(k)).compareTo(data.get(k)) < 0){
            data.swap(k, parent(k));
            k = parent(k);
        }
    }

    /**
     * 看最大的元素值
     * @return
     */
    public E findMax(){
        if(data.getSize() == 0)
            throw new IllegalArgumentException();
        return data.get(0);
    }

    /**
     * 取出堆中最大的元素
     * 思路: 先保存最大元素, 然后用最后一个元素覆盖掉最大的元素, 
     * 删除最后一个元素, 然后向下浮动形成最大堆
     * @return
     */
    public E extractMax(){
        E ret = findMax();
        data.swap(0, data.getSize()-1);
        data.removeLast();
        siftDown(0);

        return ret;
    }

    /**
     * 向下浮动
     * @param k
     */
    private void siftDown(int k){
        // 一直循环如果 k 有孩子
        while(leftChild(k) < data.getSize()){
            // 获得最大的孩子的索引
            int maxChildIndex = leftChild(k);
            if(maxChildIndex+1 < data.getSize() &&
                    data.get(maxChildIndex).compareTo(data.get(maxChildIndex+1)) < 0){
                maxChildIndex = rightChild(k);
            }

            // 如果根节点大于等于孩子
            if(data.get(k).compareTo(data.get(maxChildIndex)) >= 0) {
                break;
            }
            // 如果孩子比较大
            data.swap(k, maxChildIndex);
            k = maxChildIndex;
        }
    }

    /**
     * O(log n) 取出堆中最大的元素并替换成e
     * @param e
     * @return
     */
    public E replace(E e){
        E ret = findMax();
        data.set(0, e);
        siftDown(0);

        return ret;
    }

    public static void main(String[] args) {
        int n = 1000000;

        MaxHeap<Integer> maxHeap = new MaxHeap<>();
        Random random = new Random();
        for(int i=0; i<n; i++){
            maxHeap.add(random.nextInt(Integer.MAX_VALUE));
        }

        int[] arr = new int[n];
        for(int i=0; i<n; i++){
            arr[i] = maxHeap.extractMax();
        }

        for(int i=1; i<n; i++){
            if(arr[i-1] < arr[i]){
                throw new IllegalArgumentException();
            }
        }
        System.out.println("Good!");
    }
}

优先队列

Queue.java

public interface Queue<E> {
    int getSize();
    boolean isEmpty();
    void enqueue(E e);
    E dequeue();
    E getFront();
}

PriorityQueue.java

public class PriorityQueue<E extends Comparable<E>> implements Queue<E> {

    private MaxHeap<E> maxHeap;

    public PriorityQueue(){
        maxHeap = new MaxHeap<>();
    }

    @Override
    public int getSize() {
        return maxHeap.size();
    }

    @Override
    public boolean isEmpty() {
        return maxHeap.isEmpty();
    }

    @Override
    public void enqueue(E e) {
        maxHeap.add(e);
    }

    @Override
    public E dequeue() {
        return maxHeap.extractMax();
    }

    @Override
    public E getFront() {
        return maxHeap.findMax();
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

最大堆 和 优先队列 的相关文章

  • CVE-2023-25194漏洞 Apache Kafka Connect JNDI注入漏洞

    Apache Kafka 的最新更新解决的一个漏洞是一个不安全的 Java 反序列化问题 可以利用该漏洞通过身份验证远程执行代码 Apache Kafka 是一个开源分布式事件流平台 被数千家公司用于高性能数据管道 流分析 数据集成和任务关
  • 【机器学习】9、最小二乘法和岭回归

    文章目录 一 最小二乘法 线性回归 1 1 公式 1 2 矩阵 1 3 代码实现 二 岭回归 一 最小二乘法 线性回归 1 1 公式 最小二乘法的本质 公式推导过程 1 2 矩阵 假设我们有n个样本数据 每个数据有p个特征值 然后p个特征值
  • 十大思维导图软件推荐

    1 GitMind GitMind是一款电脑上好用的免费在线思维导图软件 主要功能有大纲视图 一键自动布局 多人云协作 插入富文本 批量管理文件 格式刷 自定义主题 快速查看历史版本 插入关系线 添加概括 一键分享思维导图 多格式文本导出
  • Jmeter—实现识别验证码登录

    在做自动化测试或压力测试时 验证码总是一个问题 在以往的压力测试经历中 测试一般在独立的测试环境中进行 可以放心禁用验证码或使用万能验证码 这个是最实用的 但是 这两天我尝试了一个使用第三方的图形图像识别工具来完成验证码识别并通过Jmete
  • Google Material Design 设计分享

    Material design 核心思想是把物理世界的体验带进屏幕 还原最贴近真实的体验 达到简洁与直观的效果 详情请参阅 https developer android com design Google对app设计的一些要求案例 1 用
  • 充电管理BQ25619使用

    特征说明 1 Power On Reset POR 该装置通过VBUS usb充电口 和VBAT 电池 中的电压较高者给内部供电 当VBUS的电压上升到超过V BUS UVLOZ值或VBAT的电压超过V BAT UVLOZ值时 睡眠比较器
  • 谈前后端分离开发模式

    前后端分离的开发模式 系统分析阶段 系分和前端开发人员约定好页面上所需的逻辑变量 进入功能开发阶段 前端开发人员进行前台页面结构 样式 行为层的代码编写 并根据约定好的变量 逻辑规则 完成不同情况展示不同的表现 而后端开发人员 只需要按照约

随机推荐

  • 【软件测试 #3】软件测试基本概念作业题

    测试项目周期包括以下哪个阶段 1 0分 A 需求测试阶段 B 测试设计阶段 C 测试执行阶段 D 以上都是 正确答案 D 我的答案 D得分 1 0分 2 在进行静态白盒测试的过程中 正式审查的基本要素不包括下列哪一项 1 0分 A 确定问题
  • 加入SC-SIG,构建智能合约及分布式应用

    为了让更多开发者参与到智能合约库组件优化中 近期社区持续开展 智能合约库有奖征码 活动 随着活动的进行大家对智能合约库的关注度与讨论度日趋高涨 在此背景下 FISCO BCOS智能合约与分布式应用专项兴趣小组 Smart Contract
  • ue4,用三星MR开发时,出现分屏,而且屏幕在左上角是怎么回事?

    这个问题困扰了几天 后来测试发现跟模式无关 跟三星MR设置无关 因为正常的地图是可以看的 最后终于找到了原因 如果设置了窗口 全屏 分辨率的话 会出现这种情况 不用的话就好了 至于为什么不能设置 目前不知道 在用MR开发 并且只开启Wind
  • 在ubuntu环境下执行openssl编译和安装

    参考链接 工具系列 Ubuntu18 04安装Openssl 1 1 1 Tinywan的技术博客 51CTO博客 密码学专题 openssl编译和安装 MY CUP OF TEA的博客 CSDN博客 openssl 编译安装 下载 sou
  • Axure学习之路01——元件介绍

    本系列博客的目的是记录Auxure软件使用的一些要点 学习课程来自 Axure 9从入门到精通 目录 一些设计资源 基本元件 图片 占位符 图像热区 动态面板 内联框架 中继器 表单元件 文本框 文本域 下拉列表 列表框 复选框 单选按钮
  • 如何产生10个100-1000的随机数

    假设max 1000 min 100 random nextInt 1000 是取0 1000之间的数 max min 1 是901 取余数所得的数应该是0 900吧 最后再加上最小数 100 0 900 最小数一起加 得出100 1000
  • Linux下安装运行keil uVision 4 (MDK v4.7)

    前几日把Keil uVision mdk v4 7 在ubuntu 12 04LTS上运行起来了 过程还算顺利 分享下步骤给需要的朋友 先上个安装完的屏幕截图 我用的是老土的Gnome Classic界面 可以看到wine菜单里有keil
  • CVE-2022-22965:Spring远程代码执行漏洞

    CVE 2022 22965 Spring Framework远程代码执行漏洞 本文仅为验证漏洞 在本地环境测试验证 无其它目的 漏洞编号 CVE 2022 22965 漏洞说明 Spring framework 是Spring 里面的一个
  • Mac下如何彻底删除IntelliJ IDEA

    有时候破解版idea 或者对idea进行各种操作后 idea 坏 掉了 那就要删除再重新安装一个 但是单纯的将整个idea移入废纸篓后 重新安装idea 会恢复到删除之前的状态 里面包含你写的代码啊 破解是改变的文件的 十分麻烦 今天老9教
  • 详解MySQL的三层架构(连接层、服务层、引擎层)

    首先来看一张很经典的图 连接层 Connectors 即为连接层 我们在访问MySQL服务前 第一件事就是建立TCP链接 经过三次握手建立连接成功后 MYSQL对TCP传输过来的账号密码做身份认证 权限获取 TCP链接收到请求后 必须要分配
  • 膜拜大佬!java设计模式刘伟课后答案

    一 先来解读 23种设计模式要点 1 单例模式 Singleton Pattern 2 工厂模式 3 抽象工厂模式 Abstract Factory Pattern 4 模板方法模式 Template Method Pattern 5 建造
  • 劳务派遣管理系统_适合人力资源外包、劳务派遣和劳务外包公司使用的人力资源管理系统有哪些?...

    人力资源外包 劳务派遣和劳务外包使用的管理系统有啥不一样 从区别上 人力资源外包里面的 包 指的是人力资源部门的职能 而劳务派遣则派的是 人 由劳务派遣单位与被派遣劳动者签订劳动合同 对于劳务外包而言 包的是 活儿 当然也包了 人 劳务外包
  • 飞书与德勤管理咨询达成战略合作,赋能企业实现智慧运营与管理

    3月19日 飞书宣布与德勤管理咨询达成战略合作 双方将携手整合资源 渠道以及解决方案 通过德勤管理咨询智慧运营方案 以及飞书高效 愉悦的一站式沟通与协作平台 为中国的各类企业客户提供高效管理 智慧管理解决方案 伴随着经济全球化与信息技术革新
  • 图像质量评估指标:PSNR / SSIM 原理及Python代码

    PSNR 峰值信噪比 Peak Signal to Noise Ratio 用于衡量两张图像之间差异 例如压缩图像与原始图像 评估压缩图像质量 复原图像与ground truth 评估复原算法性能等 公式 其中 MSE 为两张图像的均方误差
  • 【Spring Boot丨序列化、反序列化】

    序列化 反序列化 概述 Jackson 序列化和反序列化 简介 自定义序列化器 注册外部序列化程序 指定类的 Json 序列化 反序列化 主页传送门 传送 概述 序列化是将对象转换为字节序列的过程 而反序列化则是将字节序列恢复为对象的过程
  • Linux下实用批处理脚本

    本文首发在我的个人博客 https jlice top p 7q1p8 欢迎大家前去参观 么么哒 经常需要在Linux下批量处理图片 想了想 还是写个实用的批处理小脚本一劳永逸 代码 SRC为待处理目录 DST为目标目录 也就是保存处理后的
  • RedHat系统NetworkManage网络管理工具简介及相关命令(lspci、lshw)

    1 RedHat网络管理工具简介 在早期的Linux发行版本中几乎所有的网络服务都是network服务 从RHEL7开始 红帽官方建议采用NetworkManage方式配置网络 而不建议再使用network服务这种传统的方式配置网络 因为网
  • C++中对象的动态建立与释放详解

    我们知道可以用new运算符可以动态的分配内存 用delete运算符可以释放这些内存 当我们使用new运算符动态的分配一个内存之后 会自动返回一个该内存段的起始地址 也就是指针 下面先给出一个new和delete基本应用的例子 回顾一下它的基
  • Python自动化工具(自动化操作)

    一 多层目录的遍历 1 绝对路径和相对路径 相对路径 此路径下的 比绝对路径短 绝对路径 完整的路径 根目录开始 C盘等 C 或 开始 2 不同系统的路径问题 import os 来适应不同系统 版本windows和liunx 3 多层级的
  • 最大堆 和 优先队列

    最大堆 MaxHeap java import java util Random 后面测试用 public class MaxHeap