数据结构之堆的实现(图解➕源代码)

一、堆的定义

        首先明确堆是一种特殊的完全二叉树,分为大根堆和小根堆,接下来我们就分别介绍一下这两种不同的堆。

1.1 大根堆(简称:大堆)

        在大堆里面:父节点的值 ≥ 孩子节点的值

        我们的兄弟节点没有限制,只要保证每个父节点都≥孩子节点就行。

1.2 小根堆(简称:小堆)

        在小堆里面:父节点的值  孩子节点的值

        同样兄弟节点也没有限制,只要保证每个父节点都≤孩子节点就行。

这里就又用到了我们的父节点和孩子节点的位置关系了,我们可以用顺序结构来模拟完全二叉树,也就是数组来实现,话不多说,直接给公式和图形:

parent = (child-1)/2;   (任意一个child节点)

child1 = parent*2 + 1;

child2 = parent*2 + 2;

这里是运用数组下标进行计算

二、堆的实现

        我们形成堆有两种方法,一种是向下调整,一种是向上调整,在未来,经常会用到向下调整,所以我们只介绍这种方法。

2.1 向下调整法

        什么是向下调整呢?就是把我们的完全二叉树从从上往下建堆,使用向下调整法的前提就是根的左右子树必须是堆。

首先我们要建小堆,先找到同一层的小的那个和父节点交换,以此类推,直到10到叶节点或者没有比他小的。

2.2 堆的定义

在这里我们的堆的存储结构都是数组,所以在定义的时候跟定义顺序表一样,只不过在插入删除上有区别

typedef struct Heap
{
    int* arr; 
    int capacity; //数组的容量
    int size; //有效的元素个数
}Heap;

2.3 堆的初始化

//堆的初始化
void HeapInit(Heap* php)
{
    assert(php);
    php->arr = NULL;
    php->capacity = 0;
    php->size = 0;
}

2.4 堆的创建

//堆的创建
void HeapCreate(Heap* php)
{
    assert(php);
    if(php->size == php->capacity)
    {
        int newCapacity = php->capacity == 0 ? 4 : (php->capacity)*2;
        int* data = (int*) realloc(php->arr,sizeof (int)*newCapacity);
        if(data == NULL)
        {
            perror("malloc fail");
            exit(-1);
        }
        php->arr = data;
        php->capacity = newCapacity;
    }
}

2.5 堆的销毁

//堆的销毁
void HeapDestroy(Heap* php)
{
    assert(php);
    free(php->arr);
    php->arr = NULL;
    php->size = 0;
    php->capacity = 0;
}

2.6 堆的插入

在插入这里我们就要建堆了,但是由于我们的数据是顺序插入的,所以没有办法进行向下调整,这里使用向上调整的方法,原理都是一样的,向上调整就要保证插入的节点以上是堆。

void Swap(int* x,int* y)
{
    int tmp = *x;
    *x = *y;
    *y = tmp;
}

//建立大堆,向上调整
void AdjustUp(int* arr,int child)
{
    int parent = (child-1)/2;
    while (child > 0)
    {
        if(arr[child] > arr[parent])
        {
            Swap(&arr[child],&arr[parent]);
            child = parent;
            parent = (child-1)/2;
        }
        else
            break;
    }
}
//堆的插入
void HeapPush(Heap* php,int x)
{
    HeapCreate(php);
    php->arr[php->size] = x;
    php->size++;
    //建立大堆
    AdjustUp(php->arr,php->size-1);
}

2.7 删除根节点


void Swap(int* x,int* y)
{
    int tmp = *x;
    *x = *y;
    *y = tmp;
}

//建立大堆,向下调整
void AdjustDown(int*arr,int parent,int size)
{
    int child = parent*2 + 1;
    while (child < size)
    {
        if(child + 1 < size && arr[child] > arr[child+1])
        {
            child = child + 1;
        }
        if(arr[child] < arr[parent])
        {
            Swap(&arr[child],&arr[parent]);
            parent = child;
            child = parent*2 + 1;
        }
        else
            break;
    }
}
//堆的删除
void HeapPop(Heap* php)
{
    assert(php);
    assert(!HeapEmpty(php));
    Swap(&php->arr[0],&php->arr[php->size-1]);
    php->size--;
    AdjustDown(php->arr,0,php->size);
}

2.8 取堆顶的数据

//堆的根节点
int HeapTop(Heap* php)
{
    assert(php);
    assert(!HeapEmpty(php));
    return php->arr[0];
}

2.9 判断堆是否为空

//判断堆是否为空
bool HeapEmpty(Heap* php)
{
    assert(php);
    return php->size == 0;
}

2.10 堆的数据个数

//堆的节点个数
int HeapSize(Heap* php)
{
    assert(php);
    return php->size;
}

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

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

相关文章

Nacos2.2.3版本运行startup.cmd出现闪退,无错误信息解决方法

Nacos2.2.3版本运行startup.cmd出现闪退&#xff0c;无错误信息解决方法 一、问题描述二、解决方法 一、问题描述 当我下载好nacos2.2.3版解压之后&#xff0c;直接双击startup.cmd出现闪退&#xff0c;而且 没有错误提示信息。后来经过一番搜索尝试&#xff0c;终于解决了自己…

Spring 中 @Qualifier 注解还能这么用?

今天想和小伙伴们聊一聊 Qualifier 注解的完整用法&#xff0c;同时也顺便分析一下它的实现原理。 说到 Qualifier&#xff0c;有的小伙伴可能会觉得诧异&#xff0c;这也只得写一篇文章&#xff1f;确实&#xff0c;但凡有点开发经验&#xff0c;多多少少可能都遇到过 Qualif…

《算法通关村—轻松搞定合并二叉树》

《算法通关村—轻松搞定合并二叉树》 描述 leetcode 617 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵…

酒水展示预约小程序的效果如何

酒的需求度非常高&#xff0c;各种品牌、海量经销商组成了庞大市场&#xff0c;而在实际经营中&#xff0c;酒水品牌、经销商、门店经营者等环节往往也面临着品牌传播拓客引流难、产品展示预约订购难、营销难、销售渠道单一等痛点。 那么商家们应该怎样解决呢&#xff1f; 可以…

Vue3多页面开发实践

前言&#xff1a; 项目需求&#xff0c;把项目中的一个路由页面单摘出来作为一个新的项目。项目部署到服务器上后&#xff0c;通过一个链接的形式可以直接访问到新项目的页面。 解决方式&#xff1a; 使用Vue多页面方式打包项目 实现步骤&#xff1a; 1、在项目的src目录下&am…

MySQL(8):聚合函数

聚合函数介绍 聚合函数&#xff1a; 对一组数据进行汇总的函数&#xff0c;输入的是一组数据的集合&#xff0c;输出的是单个值。 聚合函数类型&#xff1a;AVG(),SUM(),MAX(),MIN(),COUNT() AVG / SUM 只适用于数值类型的字段&#xff08;或变量&#xff09; SELECT AVG(…

【IK分词器安装】

安装IK分词器&#xff1a; 下载链接&#xff08;如果es版本不同可以修改下版本号&#xff09;&#xff1a;https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip 通常下载是比较慢的&#xff1a;有需要可以从…

golang工程——opentelemetry简介、架构、概念、追踪原理

opentelemetry 简介 OpenTelemetry&#xff0c;简称OTel&#xff0c;是一个与供应商无关的开源可观测性框架&#xff0c;用于检测、生成、收集和导出 遥测数据&#xff0c;如轨迹、度量、日志。OTel的目标是提供一套标准化的供应商无关SDK、API和工具&#xff0c;用于接 收、…

Mean-Shift聚类方法

刘玉琪 跟随 出版于 台湾人工智能学院 一、说明 上一篇介绍了基于密度的分群方法——DBSCAN&#xff0c;本篇会介绍另一个分群方法——Mean Shift&#xff0c;与DBSCAN一样不需要预先知道欲分群的数量&#xff0c;而对于分群的形状也没有限制。 然而&#xff0c;这个方法是基…

网络层:控制平面

路由选择算法 路由选择算法就是为了在端到端的数据传输中&#xff0c;选择路径上路由器的最好的路径。通常&#xff0c;一条好的路径指具有最低开销的路径。最低开销路径是指源和目的地之间具有最低开销的一条路。 根据集中式还是分散式来划分 集中式路由选择算法&#xff1a…

基础Redis-Java客户端操作介绍

Java客户端操作介绍 2.基础-Redis的Java客户端a.介绍b.Jedisc.Jedis连接池d.SpringDataRedise.SpringDataRedis的序列化方式f.StringRedisTemplate 2.基础-Redis的Java客户端 a.介绍 Jedis 以Redis命令作为方法名称&#xff0c;学习成本低&#xff0c;简单实用。但是Jedis实例…

性能工作站,双十一大促,超值推荐:蝰蛇峡谷 NUC12SNKi7迷你主机,优惠抢购!

近年来&#xff0c;ITX主机和小型化系统变得越来越受欢迎。英特尔的NUC受到许多玩家们的关注。作为mini主机的代表NUC小巧设计和灵活性使它成为很多玩家和科技爱好者的选择。它的高性能和可玩性使得它在迷你型准系统市场上备受推崇。双11来临之际&#xff0c;我们分析下哪款高性…

【React】【react-globe.gl】3D Objects效果

目录 想要实现的效果实现过程踩坑安装依赖引入页面 想要实现的效果 示例地址 实现过程 踩坑 示例是通过script引入的依赖&#xff0c;但本人需要在react项目中实现该效果。按照react-globe.gl官方方法引入总是报错 Cant import the named export AmbientLight from non EcmaS…

前端的几种网络请求方式

网络请求 node编写接口 这里用到的几个包的作用 express&#xff1a;基于 Node.js 平台&#xff0c;快速、开放、极简的 Web 开发框架&#xff0c;官网&#xff1a;https://www.expressjs.com.cn/cors&#xff1a;用来解决跨域问题body-parser&#xff1a;可以通过 req.body…

Leetcode48旋转图像

思路&#xff1a;找规律 方法一、一般辅助数组解法 行列转换&#xff0c;第一行变到第三列&#xff0c;第二行变到第二列&#xff0c;第三行变到第一列 matrix[row][col] matrix[col][n-row-1] 然后复制回原数组 class Solution {public void rotate(int[][] matrix) {in…

Spring cloud负载均衡 @LoadBalanced注解原理

接上一篇文章&#xff0c;案例代码也在上一篇文章的基础上。 在上一篇文章的案例中&#xff0c;我们创建了作为Eureka server的Eureka注册中心服务、作为Eureka client的userservice、orderservice。 orderservice引入RestTemplate&#xff0c;加入了LoadBalanced注解&#x…

线性【SVM】数学原理和算法实现

一. 数学原理 SVM是一类有监督的分类算法&#xff0c;它的大致思想是&#xff1a;假设样本空间上有两类点&#xff0c;如下图所示&#xff0c;我们希望找到一个划分超平面&#xff0c;将这两类样本分开&#xff0c;我们希望这个间隔能够最大化来使得模型泛化能力最强。 如上图所…

谷歌浏览器默认https 怎么关闭

#然后把网址从 https 改成http 回车即可

用于3D Visual Grounding的多模态场景图

文章目录 引言方法1. Language Scene Graph Module Paper&#xff1a;《Free-form Description Guided 3D Visual Graph Network for Object Grounding in Point Cloud》【ICCV’2021】 Code&#xff1a;https://github.com/PNXD/FFL-3DOG 引言 3DVG任务有以下三个挑战&#x…

c语言 简单认识 指针和结构体

指针 代码 #include <stdio.h>int main(){int a 10;//指针类型需要与变量的类型相同&#xff0c;且后面需要添加一个*符号&#xff08;注意这里不是乘法运算&#xff09;表示是对于类型的指针int * p &a; //这里的&并不是进行按位与运算&#xff0c;而是取…