数据结构 - 堆

这篇博客将介绍堆的概念以及堆的实现。

1. 堆的定义:
首先堆的元素按照是完全二叉树的顺序存储的。
且堆中的某个节点总是不大于不小于其父节点的值。
根节点最大的堆叫做大堆,根节点最小的堆叫小堆。逻辑结构如下图所示:

大堆和小堆的存储方式是利用一个一维数组进行存储的,其物理存储结构如下:

因此我们可以利用数组的下标,通过子节点找到父节点,或通过父节点找到子节点,其关系如下:
        parent = ( child - 1 ) / 2; child =  parent * 2 + 1;
2. 堆的创建
那么,现在我们有一个数组 a[] = {8, 1, 4, 5, 3, 2};  在逻辑上可以看成一个完全二叉树,但是它还不是一个堆,我们要如何将其构建成一个堆呢?这里我们以构建一个小堆为例,我们从倒数第一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆,示意图如下:
3. 堆的插入 
堆的插入一般插入到数组尾部,在进行向上调整算法,直到满足堆的定义 ,示意图如下:

4. 堆的删除
 堆的删除是删除堆顶的数据,将堆顶的根数据与最后一个数据交换,在删除数组的最后一个元素,在进行向下调整堆。示意图如下:

5. 代码实现
typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;void HeapInit(HP* php);//堆的初始化
void HeapDestroy(HP* php);//内存释放
void HeapPush(HP* php, HPDataType x);//堆的创建
void HeapPop(HP* php);//删除根节点
HPDataType HeapTop(HP* php);//返回根节点
bool HeapEmpty(HP* php);//判空
int HeapSize(HP* php);//堆大小
void HeapInit(HP* php)
{assert(php);php->a = NULL;php->capacity = 0;php->size = 0;
}void HeapDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = 0;php->capacity = 0;
}void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void Adjustup(HPDataType* a, int child)//小堆调整
{int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void HeapPush(HP* php, HPDataType x)
{if (php->size == php->capacity){int newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->a, newCapacity * sizeof(HPDataType));if (tmp == NULL){perror("realloc fail");return;}php->a = tmp;php->capacity = newCapacity;}php->a[php->size] = x;php->size++;Adjustup(php->a, php->size-1);
}void AdjustDown(int* a, int n, int parent)//前提:左子树和右子树是大/小堆 
{int child = parent * 2 + 1;while (child < n){//选出左右孩子中 小/大 的那个if (child+1 < n && a[child + 1] < a[child])//右孩子可能不存在{child++;}if (a[parent] > a[child]){Swap(&a[parent],&a[child]);parent = child;child = parent * 2 + 1;}else{break;}}
}void HeapPop(HP* php)//删除堆顶的数据
//首尾数据交换,再删除,再调堆
{assert(php);assert(!HeapEmpty(php));Swap(&php->a[0], &php->a[php->size-1]);php->size--;AdjustDown(php->a,php->size,0);
}HPDataType HeapTop(HP* php) 
{assert(php);assert(!HeapEmpty(php));return php->a[0];
}bool HeapEmpty(HP* php)
{assert(php);return php->size == 0;
}int HeapSize(HP* php) 
{assert(php);return php->size;
}
6. 结果
完全二叉树:
int a[] = { 8,1,4,5,3,2 };
建堆:

打印根节点,删除根节点,内存释放: 
while (!HeapEmpty(&hp))
{int top = HeapTop(&hp);printf("%d\n", top);HeapPop(&hp);
}HeapDestroy(&hp);


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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】操作符详解,手把手教你,保姆级!!!

一&#xff0c;C语言中操作符分类 • 算术操作符&#xff1a; 、- 、* 、/ 、% • 移位操作符: > • 位操作符: & | ^ • 赋值操作符: 、 、 - 、 * 、 / 、% 、> 、& 、| 、^ • 单⽬操作符&#xff1a; &#xff01;、、--、&、*、、-、~ 、sizeof、(类…

sudo command not found

文章目录 一句话Intro其他操作 一句话 sudo 某命令 改成 sudo -i 某命令 试试。 -i 会把当前用户的环境变量带过去&#xff0c;这样在sudo的时候&#xff0c;有更高的权限&#xff0c;有本用户的环境变量(下的程序命令)。 -i, --login run login shell as the target user; a …

每日五道java面试题之springMVC篇(一)

目录&#xff1a; 第一题. 什么是Spring MVC&#xff1f;简单介绍下你对Spring MVC的理解&#xff1f;第二题. Spring MVC的优点第三题. Spring MVC的主要组件&#xff1f;第四题. 什么是DispatcherServlet?第五题. 什么是Spring MVC框架的控制器&#xff1f; 第一题. 什么是S…

2024/3/7—2575. 找出字符串的可整除数组

代码实现&#xff1a; int* divisibilityArray(char *word, int m, int *returnSize) {int n strlen(word);int *res (int*)malloc(sizeof(int) * n);long cur 0;for (int i 0; i < n; i) {cur (cur * 10 (word[i] - 0)) % m;res[i] (cur 0) ? 1 : 0;}*returnSize …

2024年最新阿里云服务器地域选择方法,以及可用区说明

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…

校招中的“熟悉linux操作系统”一般是指达到什么程度?

校招中的“熟悉linux操作系统”一般是指达到什么程度&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Linux的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&am…

如何学习I2C协议

文章目录 学习I2C协议0 懒人直达1 了解协议开发者2 从恩智浦半导体公司下载官方技术文档3 翻译成中文4 资源下载 学习I2C协议 0 懒人直达 点击直达 1 了解协议开发者 I2C&#xff08;Inter-Integrated Circuit&#xff09;协议是由荷兰皇家飞利浦电子公司&#xff08;现恩智…

多模态融合技术升级!新阶段2大融合模式取得最优性能

传统的多模态融合方法面临着模态表示不一致、灵活性不足等问题&#xff0c;难以适应日益复杂的实际需求。 而随着大模型等新技术的发展&#xff0c;研究者将这些新技术与传统的多模态融合相结合&#xff0c;提出了新阶段的融合模式&#xff0c;包括多模态大模型时代的新架构、…

深度神经网络 基本知识 记录

资料&#xff1a;https://www.bilibili.com/video/BV1K94y1Z7wn/?spm_id_from333.337.search-card.all.click&vd_source14a476de9132ba6b2c3cbc2221750b99 计划&#xff1a;3~4天 注&#xff1a;网课讲的内容比较糅杂&#xff0c;记录的内容可能会出现重复 杂 人工智能…

Rust入门:C++和Rust动态库(dll)的相互调用

无论是C调用Rust动态库还是Rust调用C动态库&#xff0c;其操作基本都是一样地简单&#xff0c;基本和C调用C的动态库没什么区别&#xff0c;只需要列出所需要导入的函数&#xff0c;并链接到相应的lib文件即可。 这里&#xff0c;在windows中&#xff0c;我们以dll动态库为例说…

【电路笔记】-NPN晶体管

NPN晶体管 文章目录 NPN晶体管1、概述2、双极NPN晶体管配置3、NPN晶体管中的α和β关系4、示例5、共发射极配置1、概述 NPN 晶体管是三端三层器件,可用作放大器或电子开关。 在前面的文章中,我们看到标准双极晶体管或 BJT 有两种基本形式。 NPN(负-正-负)配置和PNP(正-负…

《幸运的基督徒》Python

题目描述 有15个基督徒和15个非基督徒在海上遇险&#xff0c; 为了能让一部分人活下来不得不将其中15个人扔到海里面去&#xff0c; 有个人想了个办法就是大家围成一个圈&#xff0c;由某个人开始从1报数&#xff0c; 报到9的人就扔到海里面&#xff0c;他后面的人接着从1开始报…