【手写大跟堆详解】

文章目录

  • 大跟堆介绍
  • 大跟堆的结构
  • 大跟堆的应用场景
  • 大跟堆的代码实现

大跟堆介绍

大根堆(Max Heap)是一种特殊的二叉树结构,它满足以下两个条件:
1.完全二叉树:大根堆是一棵完全二叉树,即除了最后一层外,其余每一层的节点都是满的,最后一层的节点都集中在最左边。
2.堆性质:每个节点的值都大于或等于其子节点的值。
大根堆的典型操作包括插入,获取root节点的最大值。
在这里插入图片描述

大跟堆的结构

大根堆的结构
大根堆可以用数组来表示,因为它是一棵完全二叉树。对于一个存储在数组中的大根堆:
根节点的索引为 0。
给定一个节点的索引位置i:
父节点的索引为 (i - 1) / 2。
左子节点的索引为 2 * i + 1。
右子节点的索引为 2 * i + 2。

大跟堆的应用场景

大根堆(Max Heap)在许多算法和应用中都有重要的作用,特别是在需要频繁访问最大元素的场景中。以下是一些常见的应用场景:

  1. 优先队列
    优先队列是一种特殊的队列,每次出队的元素都是队列中优先级最高的元素。大根堆可以用来实现优先队列,其中堆顶元素始终是优先级最高的元素。
    应用举例:
    操作系统的任务调度:调度器选择优先级最高的任务进行执行。
    网络数据包处理:路由器处理优先级最高的数据包。
  2. 堆排序
    堆排序是一种利用堆数据结构设计的排序算法。其基本思想是将待排序序列构建成一个大根堆,此时整个序列的最大值即为堆顶元素。将堆顶元素移出堆(与堆的最后一个元素交换),然后对剩余元素重新构建堆,反复执行上述操作,直到所有元素有序。
    应用举例:
    大数据集的排序:在需要对大量数据进行排序时,堆排序的空间效率较高。
  3. 动态数据流中的最大值
    在处理动态数据流时,使用大根堆可以实时维护当前数据流中的最大值。
    应用举例:
    股票交易系统:实时维护当前交易中的最大交易量。
    传感器数据监控:实时监控传感器数据流中的最大值。
  4. 找到第 K 大的元素
    在一个无序数组中查找第 K 大的元素,可以使用大根堆来实现。首先构建一个包含数组中前 K 个元素的大根堆,然后遍历数组剩余元素,如果当前元素小于堆顶元素,则替换堆顶元素并调整堆,最终堆顶元素即为第 K 大的元素。
    应用举例:
    排名系统:在一组分数中找到第 K 高的分数。
    数据分析:在一组数据中找到第 K 大的数据点。
  5. 合并多个有序序列
    在合并多个有序序列时,可以使用大根堆来保持当前最小元素的顺序。将每个序列的首元素插入大根堆,然后每次取出堆顶元素并插入其所在序列的下一个元素,直到所有元素都被处理完毕。
    应用举例:
    外部排序:当数据量大到无法全部放入内存时,可以先将数据分块排序,然后合并多个有序块。
    多路归并排序:将多个有序的输入流合并为一个有序的输出流。
  6. 图的最短路径算法(如 Dijkstra 算法)
    在 Dijkstra 算法中,需要使用优先队列来选择当前未访问节点中距离起点最近的节点。大根堆可以用来实现这个优先队列,以保证每次都能高效地选择最短路径的下一步节点。
    应用举例:
    地图导航系统:计算从一个地点到另一个地点的最短路径。
    网络路由优化:寻找数据包在网络中传输的最优路径。
  7. 事件驱动模拟
    在事件驱动的模拟系统中,需要按照事件的发生时间顺序来处理事件。使用大根堆可以有效地管理和调度这些事件。
    应用举例:
    离散事件模拟:如模拟交通流、制造过程等。
    计算机图形学:处理动画中事件的时间调度。

大跟堆的代码实现

插入操作:
插入新元素时,将元素添加到数组的末尾(完全二叉树的最后一个位置),然后进行“上浮”操作(也称为堆化)以恢复堆的性质。
上浮操作:
将新元素与其父节点比较,如果大于父节点,则交换位置,继续向上比较,直到元素小于或等于父节点,或者到达根节点。

public void insert(int key) {
    if (size == capacity) {
        throw new RuntimeException("Heap is full");
    }

    heap[size] = key; // 将新元素放在堆尾
    int current = size;
    size++;

    // 上浮操作
    while (current != 0 && heap[parent(current)] < heap[current]) {
        swap(parent(current), current);
        current = parent(current);
    }
}

2.删除最大值操作:
删除最大值(根节点)时,将数组的最后一个元素移动到根节点位置,然后进行“下沉”操作(也称为堆化)以恢复堆的性质。
下沉操作:
将根节点与其左右子节点比较,如果小于其中一个子节点,则与较大的子节点交换位置,继续向下比较,直到元素大于或等于子节点,或者到达叶节点。

public int extractMax() {
    if (size <= 0) {
        throw new RuntimeException("Heap is empty");
    }

    int root = heap[0]; // 保存根节点
    heap[0] = heap[size - 1]; // 将最后一个元素移到根节点位置
    size--;

    // 下沉操作
    maxHeapify(0);

    return root;
}

private void maxHeapify(int i) {
    int largest = i;
    int left = leftChild(i);
    int right = rightChild(i);

    if (left < size && heap[left] > heap[largest]) {
        largest = left;
    }

    if (right < size && heap[right] > heap[largest]) {
        largest = right;
    }

    if (largest != i) {
        swap(i, largest);
        maxHeapify(largest);
    }
}

3.交换元素:
在堆的操作过程中,经常需要交换两个节点的位置。

private void swap(int i, int j) {
    int temp = heap[i];
    heap[i] = heap[j];
    heap[j] = temp;
}

4.完整的大根堆实现
以下是大根堆的完整实现,包括构造函数、插入操作、删除最大值操作和辅助方法。

public class MaxHeap {
    private int[] heap;
    private int size;
    private int capacity;

    // 构造函数
    public MaxHeap(int capacity) {
        this.capacity = capacity;
        this.heap = new int[capacity];
        this.size = 0;
    }

    // 获取父节点索引
    private int parent(int i) { return (i - 1) / 2; }

    // 获取左子节点索引
    private int leftChild(int i) { return 2 * i + 1; }

    // 获取右子节点索引
    private int rightChild(int i) { return 2 * i + 2; }

    // 插入新元素
    public void insert(int key) {
        if (size == capacity) {
            throw new RuntimeException("Heap is full");
        }

        heap[size] = key; // 将新元素放在堆尾
        int current = size;
        size++;

        // 上浮操作
        while (current != 0 && heap[parent(current)] < heap[current]) {
            swap(parent(current), current);
            current = parent(current);
        }
    }

    // 提取最大元素(根节点)
    public int extractMax() {
        if (size <= 0) {
            throw new RuntimeException("Heap is empty");
        }

        int root = heap[0]; // 保存根节点
        heap[0] = heap[size - 1]; // 将最后一个元素移到根节点位置
        size--;

        // 下沉操作
        maxHeapify(0);

        return root;
    }

    // 下沉操作
    private void maxHeapify(int i) {
        int largest = i;
        int left = leftChild(i);
        int right = rightChild(i);

        if (left < size && heap[left] > heap[largest]) {
            largest = left;
        }

        if (right < size && heap[right] > heap[largest]) {
            largest = right;
        }

        if (largest != i) {
            swap(i, largest);
            maxHeapify(largest);
        }
    }

    // 交换元素
    private void swap(int i, int j) {
        int temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }

    // 主函数示例
    public static void main(String[] args) {
        MaxHeap maxHeap = new MaxHeap(10);
        maxHeap.insert(3);
        maxHeap.insert(1);
        maxHeap.insert(4);
        maxHeap.insert(1);
        maxHeap.insert(5);
        maxHeap.insert(9);
        maxHeap.insert(2);
        maxHeap.insert(6);
        maxHeap.insert(5);

        System.out.println("Extracted max: " + maxHeap.extractMax());
        System.out.println("Extracted max: " + maxHeap.extractMax());
        System.out.println("Extracted max: " + maxHeap.extractMax());
    }
}

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

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

相关文章

ORACLE 资源管理参数与等待事件resmgr:cpu quantum

RESOURCE_MANAGER_PLAN 先来看下参数的含义 官网链接&#xff1a;RESOURCE_MANAGER_PLAN (oracle.com) 意思翻译过来这个参数用于资源计划。后边的看完也不是很明白具体的作用 于是参考了以下文章 Oracle 参数 RESOURCE_MANAGER_PLAN 官方解释&#xff0c;作用&#xff0c;…

Kubernetes——Pod详解

目录 一、Pod基础概念 1.概念 2.使用方式 3.Pause容器 3.1网络 3.2存储 4.Pod容器分类 4.1自主式Pod 4.2控制器管理的Pod 二、Pod的分类 1.基础容器&#xff08;infrastructure container&#xff09; 2.初始化容器&#xff08;initcontainers&#xff09; 2.1Ini…

前端vue用el-table如何实现表头内容过长换行处理,实现换行效果

前端vue用el-table如何实现表头内容过长换行处理&#xff0c;实现换行效果 这是效果图 有两种方法&#xff0c;一种简易版本&#xff0c;一种万能方法,都是el-table&#xff0c;先看文档 表头标题是可以自定义的 方法一 label的解释写在代码里面了&#xff0c;这里会自动形成换…

Edge浏览器“此页存在问题”解决思路

Edge浏览器显示“此页存在问题”解决思路 大家平时使用Edge浏览器时&#xff0c;是否和我一样会突然出现“此页存在问题”的情况&#xff1f; 经过百度查询后我找了一种情况和解决办法&#xff0c;能够大大减少这类问题的出现。出现“此页存在问题”可能是因为之前使用过软件…

C++相关概念和易错语法(13)(string的模拟实现)

string由于存在字符串和单字符的概念&#xff0c;使得它的一些接口&#xff0c;实现要比vector多一些。本质上来看string的实现是在顺序表的基础上加入串相关的操作。下面我会分享如何模拟实现string&#xff0c;这可以进一步提高我们对string的熟练程度。 1.构造函数、拷贝构…

Mysql与Navicat可视化命令大全 ----项目实战

软件准备&#xff1a;✍Mysql8.0下载地址&#xff08;推荐&#xff09;✍Navicat 16 下载地址&#xff08;推荐&#xff09; 注&#xff1a;不会安装看主页&#xff0c;关注我&#xff0c;免费指导&#xff0c;接计算机毕设☑ -----------------------------------------------…

交换机连接方式

一、级联方式 级联是将多个交换机或其他网络设备依次连接&#xff0c;形成一个层次结构&#xff0c;从而扩展网络的覆盖范围和端口数量。 在级联连接中&#xff0c;数据信号会从一个设备依次传递到下一个设备。每个设备都会接收并处理来自上级设备的数据&#xff0c;并将其转…

【MySQL精通之路】MySQL8.0新增功能-原子DDL语句支持

太长不看系列&#xff1a; 本文一句话总结&#xff0c;MySQL8.0支持多条DDL语句执行时的原子性了&#xff08;仅限Innodb&#xff09; 本文属于下面这篇博客的子博客&#xff1a; 【MySQL精通之路】MySQL8.0官方文档-新增功能 1.意义描述 MySQL 8.0支持原子数据定义语言&…

设置我们JavaScript设置的开发环境

你想设置一个用于编写Java脚本的开发环境,对吧?我们会在接下来的笔记中写一些JavaScript代码,所以我们需要一个开发环境。那么我们需要选择哪种开发环境呢? 通常情况下,对于像Java或C#这样的语言,你需要进行一些安装,对吧?你需要下载Java或某个运行时环境,并设置好路…

uniapp集成websocket不断线的处理-打牌记账

背景 近期在开发打牌记账微信小程序时&#xff0c;我们将房间这个业务场景做成了类似聊天室功能。 对房间内发生的动作&#xff0c;都能实时对其他人可见。 如:转账&#xff0c;离开&#xff0c;加入&#xff0c;结算等动作 其他人员都能实时接收到推送消息&#xff0c; 这个时…

Android模块化项目搭建和模块之间跳转传值(1)

一、背景 近段时间 由于工作没有这么繁忙&#xff0c;于是总结了一下项目中的模块化处理&#xff0c;并且这也是在众多面试中会问到的问题&#xff0c;希望能够帮助到在学习或者了解模块化的同学。 二、项目搭建 1、其实模块化就是将众多功能模块分成一个一个的模块进行开发…

<项目> 云备份

目录 一、简单认识 二、实现目标 三、服务端程序负责功能及功能模块划分 四、客户端程序负责功能及功能模块划分 五、环境搭建 &#xff08;一&#xff09;gcc 7.3 &#xff08;二&#xff09;安装jsoncpp库 &#xff08;三&#xff09;下载bundle数据压缩库 &#xf…

聊聊 JSON Web Token (JWT) 和 jwcrypto 的使用

哈喽大家好&#xff0c;我是咸鱼。 最近写的一个 Python 项目用到了 jwcrypto 这个库&#xff0c;这个库是专门用来处理 JWT 的&#xff0c;JWT 全称是 JSON Web Token &#xff0c;JSON 格式的 Token。 今天就来简单入门一下 JWT。 官方介绍&#xff1a;https://jwt.io/intr…

添加、修改和删除列表元素

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 添加、修改和删除列表元素也称为更新列表。在实际开发时&#xff0c;经常需要对列表进行更新。下面我们介绍如何实现列表元素的添加、修改和删除。 …

vs无法打开或包括文件”QTxxx“

vs创建项目时默认引入core、gui、和widgets等模块&#xff0c;在需要网络通讯或者图表等开发时需要添加相应模块。 点击扩展 -> QT VS Tools -> QT Project Setting->Qt Modules&#xff0c;添加相应模块即可

【Jenkins】Centos7安装Jenkins(环境:JDK11,tomcat9,maven3.8)

目录 Jenkins部署环境Maven安装1.上传安装包2.解压3.配置Maven环境变量4.使配置文件立即生效5.校验Maven安装6.Maven配置阿里云仓库7.Maven配置依赖下载位置 Git安装安装监测安装 JDK17安装1.查看旧版本JDK2.卸载旧版本JDK3.查看是否卸载干净4.创建java目录5.下载JDK11安装包6.…

kettle从入门到精通 第六十二课 ETL之kettle job中发送邮件(带多个附件),闭坑指南

1、今天群里一个朋友加我微信遇到问下向我求助。一顿测试下来发现原来是使用kettle姿势不对&#xff0c;对kettle没有完全驾驭导致的&#xff0c;今天和大家一起分享下这个问题。 2、先自我膨胀下&#xff0c;自从写kettle系列文章之后认识了很多朋友&#xff0c;同时文章也帮助…

设计模式6——单例模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 单例模式&#xff08;Singleto…

1-4月我国5G用户、流量占比均过半,呈现平稳增长态势!

1-4月份&#xff0c;通信行业整体运行平稳。电信业务量收平稳增长&#xff1b;5G、千兆光网等新型基础设施建设持续推进&#xff0c;网络连接用户规模不断扩大&#xff0c;移动互联网接入流量较快增长。 一、总体运行情况 电信业务收入稳步增长&#xff0c;电信业务总量增速保持…

vue3.0(十)双向数据绑定原理和v2.0对比

文章目录 MVVM框架1 理解ViewModel2 MVVM的优点 vue2.0 双向数据绑定原理1 实现双向数据绑定2 实现3 Vue2.0 缺点和解决办法 vue3.0 双向数据绑定原理vue2.0和vue3.0 的差异Vue2.0Vue3.0Object.defineProperty和Proxy的对比 MVVM框架 MVVM&#xff08;Model-View-ViewModel&am…