数据结构笔记堆

news2024/11/24 16:31:34

1.堆的定义

//堆是一颗完全二叉树,堆一般由优先队列来实现

堆分为两种:

1.大顶堆中父亲结点的值大于或者等于孩子结点的值,以它为根结点的子树,它是最大值

(顶点是最大值,顶点指的是树的根结点或者子树的根结点)

2.小顶堆的父亲结点的值小于或者等于孩子结点的值,以它为根结点的子树,它是最小值

//不管是大顶堆和小顶堆都无法直接通过堆的结构比较出左右孩子的大小关系

即root->data >= root->lchild->data, root->data >= root->rchild->data

但无法直接得出root->lchild->data和root->rchild->data的大小关系

  1. 怎么建成一个堆

(1)表示一个堆

//堆是一颗完全二叉树,最简洁的方法就是使用数组进行表示(根结点下标为1,左孩子为2*X, 右孩子为2*X+1)

(2)如何调整一个二叉树,使其成为一个堆

//先左右孩子进行比较,找出最大的再和要调整的父亲结点进行比较,如果大于就交换二者的值,交换后处理的结点的下标要改成原来被交换孩子的下标,逐层向下调整,直到该结点的值是其子树的最大值为止。

代码:

void downAdjust(int low, int high) {//low为父亲结点,high为二叉树的边界; 
    int i = low, j = 2 * low;//i为要处理的结点,j为要处理结点的左孩子(也可以看出要进行对比的孩子);
    while(j <= high) {
        //先对比左右孩子;
        if(j + 1 <= high) {
            if(j + 1 <= high && heap[j + 1] > heap[j]) {//首先右孩子要存在,右孩子更大; 
                j = j + 1;
            }
        }
        if(heap[j] > heap[i]) {//右孩子或者左孩子比父亲结点还大; 
            swap(heap[j], heap[i]);
            i = j;//结构改变,更改下标;
            j = i * 2;//记得更换左孩子,不能让j还指在上层; 
        } else {
            break;//左右孩子都比处理结点小,则说明处理结点的位置是对了,可以退出了; 
        } 
    }  
}

调整完全二叉树,使其成为一个大顶堆

void create(int heap[], int n) {
    for(int i = n / 2; i >= 1; i--) {
        downAdjust(n/2, n);
    }
}
  1. 完全二叉树的叶子结点个数等于n/2(偶数等于n/2, 奇数等于n/2+1,因为这里不影响,n/2求出来的是最后一个非叶子结点的下标),下标1到n/2全部都是非叶子结点,n/2以后的都是叶子结点;

  1. 从下往上进行调整, 这样上一层就可以利用我下一层已经调整好的该子树的最大值进行比对,再接着往上推,直到遍历完堆的根结点。

完全二叉树->从最后一个非叶子结点向根结点进行调整->大/小顶堆

  1. 栈的基本操作:

1)删除栈顶元素

void DeleteTop() {
    heap[1] = heap[n--];//用最后一个元素覆盖,并让元素个数减1; 
    downAdjust(1, n);//从根结点从下调整; 
}

(2)插入元素

插入元素是先把它放到堆的最后面,然后再往上比较,如果比父亲结点小了就不用动了,就留在哪里

即插入元素是要向上调整,删除元素是向下调整,直到遇到自己的位置而停下来。

向上调整和向下调整的代码差不多,向下调整比向上调整简单,顶上的元素被换下来肯定比原来的元素要大的,所以被换下来的元素不需要调整。

代码:

void upAdjust(int low, int high) {//low一般是1,根结点,high是插入结点的下标; 
    int i = high, j = n/2;//j是i的父亲结点, i不管是左孩子还是右孩子算出来都是其父结点;
    while(j >= low) {
        if(heap[i] > heap[j]) {//不想向下调整这么麻烦,一定有父结点; 
            swap(heap[i], heap[j]);
            i = j;
            j = i / 2;
        } else {
            break;
        }
    } 
}

void insert(int x) {
    heap[++n] = x;
    upAdjust(1, n);
}

全部代码:

#include<iostream>
#include<queue>

using namespace std;

const int Maxn = 10010;
int heap[Maxn] = {0, 85, 55, 82, 57, 68, 92, 99, 98, 66, 56};
int n = 10;
void downAdjust(int low, int high) {//low为父亲结点,high为二叉树的边界; 
    int i = low, j = i * 2;//i为要处理的结点,j为要处理结点的左孩子(也可以看出要进行对比的孩子);
    while(j <= high) {
        //先对比左右孩子;
        if(j + 1 <= high && heap[j + 1] > heap[j]) {//首先右孩子要存在,右孩子更大; 
            j = j + 1;
        }
        if(heap[j] > heap[i]) {//右孩子或者左孩子比父亲结点还大; 
            swap(heap[j], heap[i]);
            i = j;//结构改变,更改下标;
            j = i * 2;//记得更换左孩子,不能让j还指在上层; 
        } else {
            break;//左右孩子都比处理结点小,则说明处理结点的位置是对了,可以退出了; 
        } 
    }  
}

void create(int heap[], int n) {
    for(int i = n / 2; i >= 1; i--) {
        downAdjust(i, n);
    }
}
void DeleteTop() {
    heap[1] = heap[n--];//用最后一个元素覆盖,并让元素个数减1; 
    downAdjust(1, n);//从根结点从下调整; 
}

void upAdjust(int low, int high) {//low一般是1,根结点,high是插入结点的下标; 
    int i = high, j = n/2;//j是i的父亲结点, i不管是左孩子还是右孩子算出来都是其父结点;
    while(j >= low) {
        if(heap[i] > heap[j]) {//不想向下调整这么麻烦,一定有父结点; 
            swap(heap[i], heap[j]);
            i = j;
            j = i / 2;
        } else {
            break;
        }
    } 
}

void insert(int x) {
    heap[++n] = x;
    upAdjust(1, n);
}

int main() {
    create(heap, n);
    for(int i = 1; i <= n; i++)
        cout << heap[i] << " ";
    cout <<"\n";
    insert(100);
    for(int i = 1; i <= n; i++)
        cout << heap[i] << " ";
    cout <<"\n";    
    
    
    return 0;
}

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

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

相关文章

详解 matplotlib.pyplot ,Python 初学者真能看懂

Matplotlib 是一个 Python 中的 2D 绘图库&#xff0c; pyplot 模块是一个方便使用 Matplotlib 的接口。 下面是 pyplot 模块中的五个重要的知识点&#xff1a; 【创建图形】&#xff1a; pyplot 模块提供了许多简单易用的函数来创建图形&#xff0c;如 plot、scatter、bar、h…

Python语言零基础入门教程(十)

Python 字符串 字符串是 Python 中最常用的数据类型。我们可以使用引号 ( ’ 或 " ) 来创建字符串。 创建字符串很简单&#xff0c;只要为变量分配一个值即可。例如&#xff1a; var1 Hello World! var2 "Python Runoob"Python 访问字符串中的值 Python 不…

TCP连接的状态详解以及故障排查(五)

同时打开 两个应用程序同时执行主动打开的情况是可能的&#xff0c;虽然发生的可能性较低。每一端都发送一个SYN,并传递给对方&#xff0c;且每一端都使用对端所知的端口作为本地端口。例如&#xff1a; 主机a中一应用程序使用7777作为本地端口&#xff0c;并连接到主机b 888…

【Python入门第四天】Python 注释

开始之前&#xff0c;先给大家讲个笑话… 程序员最讨厌的两种人&#xff1a;写代码不写注释的人和让自己写注释的人。 注释可用于解释 Python 代码。 注释可用于提高代码的可读性。 在测试代码时&#xff0c;可以使用注释来阻止执行。 创建注释 注释以 &#xff03; 开头&am…

低代码开发平台|生产管理-生产加工搭建指南

1、简介1.1、案例简介本文将介绍&#xff0c;如何搭建生产管理-生产加工。1.2、应用场景在主生产计划列表中下达加工后&#xff0c;在加工单列表可操作领料、质检。2、设置方法2.1、表单搭建1&#xff09;新建表单【产品结构清单&#xff08;BOM&#xff09;】&#xff0c;字段…

32单片机矩阵键盘-同列组合键不能识别故障-已解决

一、电路原理 1.1. 矩阵键盘电路 1.2. gd32f103单片机端是iic,中间经过一个pca9535芯片。 1.3 pca9535 的功能请参考相关文档 这里主要用到的是设置输入输出模式&#xff0c;读取输入值&#xff0c;输出高或者输出低等功能。 二、基本要求 2.1 单个按键识别 2.2 组合键识别…

米尔基于ARM嵌入式核心板的电池管理系统(BMS)

BMS全称是Battery Management System&#xff0c;电池管理系统。它是配合监控储能电池状态的设备&#xff0c;主要就是为了智能化管理及维护各个电池单元&#xff0c;防止电池出现过充电和过放电&#xff0c;延长电池的使用寿命&#xff0c;监控电池的状态。 图片摘自网络 电池…

【C++入门】命名空间,输出输入,缺省参数,函数重载

文章目录命名空间C输入与输出缺省参数函数重载命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是对标 识符的名称进行本地化&#xff0…

电子技术——共源共栅放大器

电子技术——共源共栅放大器 之前我们提到过&#xff0c;提高基础增益单元&#xff08;共源放大器&#xff09;的一种方法是提高其 ror_oro​ 的阻值&#xff0c;之后我们学过共栅放大器作为电流缓冲器可以做到这一点&#xff0c;自然地我们就得到了终极解决方案&#xff0c;也…

Fluid-数据缓存亲和性调度原理解析

前言在Fluid中&#xff0c;Dataset资源对象中所定义的远程文件是可被调度的&#xff0c;这意味着你能够像管理你的Pod一样管理远程文件缓存在Kubernetes集群上的存放位置。另外&#xff0c;Fluid同样支持对于应用的数据缓存亲和性调度&#xff0c;这种调度方式将应用(e.g. 数据…

iOS 导航条isTranslucent几个注意点(iOS11及iOS13的变化)

文章主要针对11及13之后的导航变化进行总结&#xff0c;主要是设置透明度时对转场&#xff0c;包括标题&#xff0c;背景透明&#xff0c;图片&#xff0c;颜色等设置的影响。 每一个iOS版本的发布苹果最不稳写的可能就数这个导航条了吧&#xff0c;改了又改。 因此isTranslu…

Prometheus监控Java-JMX

一、什么是 JMX Exporter ? JMX Exporter 利用 Java 的 JMX 机制来读取 JVM 运行时的一些监控数据&#xff0c;然后将其转换为 Prometheus 所认知的 metrics 格式&#xff0c;以便让 Prometheus 对其进行监控采集。 那么&#xff0c;JMX 又是什么呢&#xff1f;它的全称是&a…

【Redis场景4】单机环境下秒杀问题

单机环境下的秒杀问题 秒杀下单功能及并发测试 完整代码GitHub&#xff1a;https://github.com/xbhog/hm-dianping/tree/20230130-xbhog-redisSpike 秒杀条件分析&#xff1a; 秒杀是否开始或结束&#xff0c;如果尚未开始或已经结束则无法下单库存是否充足&#xff0c;不足…

【体验测评】ChatGDP

前言 今天在去打针之前测试了下比较火的ChatGPT,总得来说还是比较好用的&#xff0c;尤其是跟浏览器搭配可以当摘要看&#xff0c;然后再进行细化查阅。 ​针对可以写论文跟交作业&#xff0c;我觉得查重率这一关比较麻烦&#xff0c;不现实&#xff0c;尤其是参与人增多的时…

php宝塔搭建部署实战易优养殖基地网站源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的易优养殖基地网站源码&#xff0c;感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&#xff0c;宝…

选择游戏开发工具的原则

本文首发于微信公众号&#xff1a; 小蚂蚁教你做游戏。欢迎关注领取更多学习做游戏的原创教程资料&#xff0c;每天学点儿游戏开发知识。嗨&#xff01;大家好&#xff0c;我是小蚂蚁。昨天为了给我的精致1010游戏方便的增加更多关卡&#xff0c;我用 Unity 做了个关卡编辑器&a…

pycharm的terminal与Project interpreter 配置环境不一致的问题

考虑自己的项目名中是否出现了中文&#xff0c;我是因为这个原因导致Terminal 前面出现了PS&#xff0c;用第2条解决切换终端环境后还是安装包不一致。终端出现PS&#xff0c;考虑在settings中搜索找到Terminal&#xff0c;修改其Shell path为cmd.exe&#xff0c;关闭重新打开T…

SpringCloud保姆级搭建教程三---Feign

1、第一点就是要明白服务与服务之间在怎么样的情况下&#xff0c;如何使用feign答&#xff1a;服务A要调用服务B的某个controller方法的时候&#xff0c;服务A就需要使用feign ,和服务B是没关系的所以&#xff0c;首先&#xff0c;在服务A中添加feign的依赖&#xff0c;我这里就…

nodejs基于vue高校图书馆座位预约系统

目录 1 绪论 1 1.1课题背景 1 1.2课题研究现状 1 1.3初步设计方法与实施方案 2 1.4本文研究内容 2 2 系统开发环境 4 2.1 使用工具简介 4 2.2 环境配置 4 2.3 B/S结构简介 4 2.4 MySQL数据库 5 2.5 框架介绍 5 3 系统分析 63.1系统可行性分析 6 3.1.1经济可行性 6 3.1.2技术可行…

软件测试电商项目实战(写进简历没问题)

前言 说实话&#xff0c;在找项目的过程中&#xff0c;我下载过&#xff08;甚至付费下载过&#xff09;N多个项目、联系过很多项目的作者&#xff0c;但是绝大部分项目&#xff0c;在我看来&#xff0c;并不适合你拿来练习&#xff0c;它们或多或少都存在着“问题”&#xff…