数据结构7——二叉树的顺序结构以及堆的实现
在上篇文章数据结构6——树与二叉树中,我们了解了树和二叉树的概念,接着上篇文章,在本篇文章中我们学习二叉树顺序结构的实现。
目录
1. 二叉树的顺序存储结构
2. 堆的概念及结构
1. 堆的概念
2. 堆的结构
3. 堆的实现
1. 堆节点
2. 交换节点
3. 打印
4. 堆的插入
向上调整:
插入:
5. 堆的删除
向下调整:
删除:
6. 初始化
7. 销毁
验证:
源代码:
Heap.h:
Heap.c:
test.c:
1. 二叉树的顺序存储结构
二叉树一般可以使用两种结构存储,一种是顺序结构,一种是链式结构。本篇文章我们先来研究二叉树的顺序存储,下篇文章详解二叉树的链式存储。
普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。
如图: 完全二叉树顺序存储:

非完全二叉树顺序存储:

2. 堆的概念及结构
1. 堆的概念
简单来说,堆除了是一棵完全二叉树之外,还要满足堆序性。
堆中每个节点的值都大于等于其子节点的值,根节点是堆中最大的元素,这样的堆称为最大堆或大根堆;
相反的,堆中每个节点的值都小于等于其子节点的值,根节点是堆中最小的元素,这样的堆称为最小堆或小根堆;
2. 堆的结构


3. 堆的实现
(本篇文章只实现最小堆,最大堆与最小堆是相同的道理)
1. 堆节点
typedef int HPDataType;
//堆的物理结构与顺序表相似
typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;
2. 交换节点
//交换
void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}
3. 打印
//打印
void HeapPrint(HP* php)
{assert(php);for (size_t i = 0; i < php->size; i++){printf("%d ", php->a[i]);}printf("\n");
}
4. 堆的插入
可是现在堆属性并不满足,因为30在5的上面,这是一个最小堆,我们需要将小的数字在上面。
为了恢复堆属性,我们需要交换30和5:

可是现在仍旧没有满足最小堆的堆属性,所以还需要交换10和5:

此时才得到了最小堆。
因此在插入数据后每次都要进行向上调整,于是向上调整的实现为:
向上调整:
//向上调整
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 = (parent - 1) / 2;}else{break;}}
}
插入:
//插入
void HeapPush(HP* php, HPDataType x)
{assert(php);//判断是否需要扩容if (php->size == php->capacity){int newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = realloc(php->a, sizeof(HPDataType) * newCapacity);if (tmp == NULL)//检查是否扩容成功{perror("realloc fail");exit(-1);}php->a = tmp;php->capacity = newCapacity;}php->a[php->size] = x;php->size++;AdjustUP(php->a, php->size - 1);//传数组的最后一个数据
}
5. 堆的删除
由于堆顶是最大或最小元素,为了满足堆属性,所以堆中每次只能删除堆顶元素,一般的做法是先将堆顶元素与数组末尾元素先交换,再删除末尾元素。

可是现在40在了堆顶,反而成了最大的元素,并不满足最小堆,这时就需要向下调整:

每次删除都要调整,所以向下调整的具体实现为:
向下调整:
//向下调整
void AdjustDown(HPDataType* 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[child] < a[parent]){Swap(&a[child], &a[parent]);//继续往下调整parent = child;child = parent * 2 + 1;}else{break;}}
}
删除:
//删除
void HeapPop(HP* php)
{assert(php);assert(php->size > 0);Swap(&php->a[0], &php->a[php->size - 1]);--php->size;AdjustDown(php->a, php->size, 0);
}
6. 初始化
//初始化
void HeapInit(HP* php)
{assert(php);php->a = NULL;php->size = 0;php->capacity = 0;
}
7. 销毁
//销毁
void HeapDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = php->capacity = 0;
}
验证:
int main()
{int a[] = { 9,3,7,10,24,14,28,72,21,5 };HP hp;HeapInit(&hp);for (size_t i = 0; i < sizeof(a) / sizeof(int); i++){HeapPush(&hp, a[i]);}HeapPrint(&hp);HeapDestroy(&hp);return 0;
}

源代码:
Heap.h:
#pragma once#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int HPDataType;
//堆的物理结构与顺序表相似
typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;//交换
void Swap(HPDataType* p1, HPDataType* p2);//打印
void HeapPrint(HP* php);//初始化
void HeapInit(HP* php);//向上调整
void AdjustUP(HPDataType* a, int child);
//插入
void HeapPush(HP* php, HPDataType x);//向下调整
void AdjustDown(HPDataType* a, int n, int parent);
//删除
void HeapPop(HP* php);//销毁
void HeapDestroy(HP* php);
Heap.c:
#include "Heap.h"//交换
void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}//打印
void HeapPrint(HP* php)
{assert(php);for (size_t i = 0; i < php->size; i++){printf("%d ", php->a[i]);}printf("\n");
}//向上调整
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 = (parent - 1) / 2;}else{break;}}
}//插入
void HeapPush(HP* php, HPDataType x)
{assert(php);//判断是否需要扩容if (php->size == php->capacity){int newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = realloc(php->a, sizeof(HPDataType) * newCapacity);if (tmp == NULL)//检查是否扩容成功{perror("realloc fail");exit(-1);}php->a = tmp;php->capacity = newCapacity;}php->a[php->size] = x;php->size++;AdjustUP(php->a, php->size - 1);//传数组的最后一个数据
}//向下调整
void AdjustDown(HPDataType* 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[child] < a[parent]){Swap(&a[child], &a[parent]);//继续往下调整parent = child;child = parent * 2 + 1;}else{break;}}
}//删除
void HeapPop(HP* php)
{assert(php);assert(php->size > 0);Swap(&php->a[0], &php->a[php->size - 1]);--php->size;AdjustDown(php->a, php->size, 0);
}//初始化
void HeapInit(HP* php)
{assert(php);php->a = NULL;php->size = 0;php->capacity = 0;
}//销毁
void HeapDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = php->capacity = 0;
}
test.c:
int main()
{int a[] = { 9,3,7,10,24,14,28,72,21,5 };HP hp;HeapInit(&hp);for (size_t i = 0; i < sizeof(a) / sizeof(int); i++){HeapPush(&hp, a[i]);}HeapPrint(&hp);HeapDestroy(&hp);return 0;
}相关文章:
数据结构7——二叉树的顺序结构以及堆的实现
在上篇文章数据结构6——树与二叉树中,我们了解了树和二叉树的概念,接着上篇文章,在本篇文章中我们学习二叉树顺序结构的实现。 目录 1. 二叉树的顺序存储结构 2. 堆的概念及结构 1. 堆的概念 2. 堆的结构 3. 堆的实现 1. 堆节点 2. 交…...
leetcode hot100 之【LeetCode 21. 合并两个有序链表】 java实现
LeetCode 21. 合并两个有序链表 题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接两个链表的节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4]示例 2: 输入:l1 …...
Android Camera系列(五):Camera2
Life was like a box of chocolates, you never know what you’re gonna get. 生命就像一盒巧克力,你永远无法知道下一个是什么味道的。 Android Camera系列(一):SurfaceViewCamera Android Camera系列(二࿰…...
从DexMV、VideoDex、MimicPlay到SeeDo:从人类视频中学习:机器人的主流训练方法之一
前言 在此文《UMI——斯坦福刷盘机器人:从手持夹持器到动作预测Diffusion Policy(含代码解读)》的1.1节开头有提到 机器人收集训练数据一般有多种方式,比如来自人类视频的视觉演示 有的工作致力于从视频数据——例如YouTube视频中进行策略学习 即最常见…...
如何在Docker中运行Squid
测试环境 VMware Rocky Linux 9.4 实现步骤 过程:写一个Dockerfile构建Squid镜像; 再写一个启动脚本start_squid.sh,在启动脚本中配置并运行Squid。 编写Dockerfile 以rockylinux9.3做基础镜像,通过yum安装Squid, 拷贝squid.conf FROM …...
Ubuntu22.04 加入AD域
Ubuntu22.04 加入AD域 要在Ubuntu 22.04上加入Active Directory (AD) 域,你可以使用realmd和sssd服务。以下是加入AD域的步骤和示例配置: 更新系统软件包列表: sudo apt update 下载安装必要的软件包: sudo apt install realm…...
Docker 构建 Miniconda3 Python 运行环境实战指南
Docker 构建 Miniconda3 Python 运行环境实战指南 文章目录 Docker 构建 Miniconda3 Python 运行环境实战指南一 准备 environment.yml二 获取项目 pip 信息三 Dockerfile 编写四 构建多平台镜像1 准备组件2 构建镜像3 导出镜像4 导入镜像 五 注意事项 本文详细介绍了如何通过 …...
029 elasticsearch文档管理(ElasticsearchRepository、ElasticsearchRestTemplate)
文章目录 BlogRepository.javaBlogRepositoryTest.javaBulkTest.java 文档的管理 ElasticSearchRepository接口 使用方法: 创建一个接口,继承于ElasticSearchRepository,指定使用的Entity类及对应主键数据类型 Springboot自动扫描接口并创建代…...
【Flutter】Dart:Isolate
在 Dart 和 Flutter 中,所有的代码默认都运行在单一的线程(即主线程)上,这个线程也叫做 UI 线程。当进行耗时操作(如复杂计算或网络请求)时,如果不使用多线程处理,主线程会被阻塞&am…...
微信小程序 页面间传递数据
在小程序中,给页面传递参数通常有以下几种方法: 通过URL传递参数: 在小程序中,可以在页面的路径后面添加参数,然后在页面的 onLoad 函数中获取这些参数。 // 在app.json中配置页面路径 "pages": [{"pat…...
前端_005_Nodejs
文章目录 npm包管理器cjs和mjsYarn包管理器 1.Node.js 是js的一个运行环境,从nodejs诞生后js代码不局限于只在浏览器中执行,此外还能再nodejs里写服务端,用js可以前后端全栈开发 2.Node.js不跟浏览器一样默认含有document,window对象…...
SpringCache缓存介绍
1.为什么需要缓存 前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果: 使用缓存是一个很…...
python实战(一)——iris鸢尾花数据集分类
一、任务背景 本文是python实战系列专栏的第一篇文章,我们将从分类开始由浅入深逐步学习如何使用python完成常规的机器学习/深度学习任务。iris数据集是经典的机器学习入门数据集,许多分类任务教程都会以这个数据集作为示例,它的数据量是150条…...
k8s-对命名空间资源配额
对k8s命名空间限制的方法有很多种,今天来演示一下很常用的一种 用的k8s对象就是ResourceQuota 一:创建命名空间 kubectl create ns test #namespace命名空间可以简写成ns 二: 对命名空间进行限制 创建resourcequota vim resourcequ…...
Failed to connect to github.com port 443
git push无法连接443端口 **问题1****方法一:取消代理设置**git命令 其他解决方案1. **设置 Git 使用 HTTP 而不是 HTTPS**2. **检查证书**3. **配置 Git 忽略 SSL 验证(不推荐)**4. **检查代理设置** 问题1 Failed to connect to github.com…...
【设计模式系列】简单工厂模式
一、什么是简单工厂模式 简单工厂模式(Simple Factory Pattern)是一种设计模式,其中包含一个工厂类,根据传入的参数不同,返回不同类的实例。这个工厂类封装了对象的创建逻辑,使得客户端代码可以从直接创建…...
给定一个正整数n随机生成n个字节即生成2n个十六进制数将其组成字符串返回secrets.token_hex(n)
【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 给定一个正整数n 随机生成n个字节 即生成2n个十六进制数 将其组成字符串返回 secrets.token_hex(n) [太阳]选择题 根据题目代码,执行的结果错误的是? import secrets …...
[Gtk] 工程
MediaPlayer 可执行文件工程 结构 . ├── BUILD ├── ButtonHelper.cpp ├── ButtonHelper.h ├── CMakeLists.txt ├── DrawingAreaHelper.cpp ├── DrawingAreaHelper.h ├── layout.ui └── main.cpp CMakeLists.txt # 1) cmake basic cmake_minimum_r…...
基于Multisim的汽车尾灯控制电路设计与仿真
假设汽车尾部左右量测各有3个指示灯(用发光二极管模拟)1. 汽车正常运行时指示灯全灭;2.右转弯时,右侧3个指示灯按右循环顺序点亮;.3. 左转弯时,左侧3个指示灯按左循环顺序点亮;4.临时刹车时所有…...
Leetcode 3326. Minimum Division Operations to Make Array Non Decreasing
Leetcode 3326. Minimum Division Operations to Make Array Non Decreasing 1. 解题思路2. 代码实现 题目链接:3326. Minimum Division Operations to Make Array Non Decreasing 1. 解题思路 这一题的话就是要看出来题中给出的operation的本质事实上就是将任意…...
5分钟上手Velocity动态主题动画:让界面动效随用户偏好智能切换
5分钟上手Velocity动态主题动画:让界面动效随用户偏好智能切换 【免费下载链接】velocity Accelerated JavaScript animation. 项目地址: https://gitcode.com/gh_mirrors/ve/velocity Velocity是一款高性能的JavaScript动画库,专注于提供流畅、高…...
谱聚类实战:如何让声纹模型自动分辨一段录音里有几个人说话?
谱聚类在声纹识别中的应用:如何自动判断录音中的说话人数量 想象一下,你手头有一段长达两小时的会议录音,里面有五位不同声线的参与者交替发言。作为开发者,你需要设计一个系统,不仅能识别每个人的声音特征,…...
不要让接口过早失去可选项
这,是一个采用C精灵库编写的程序,它画了一幅漂亮的图形: 复制代码 #include "sprites.h" //包含C精灵库 Sprite turtle; //建立角色叫turtle void draw(int d){for(int i0;i<5;i)turtle.fd(d).left(72); } int main(){ …...
2026届必备的十大降重复率工具实际效果
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 当前,人工智能生成内容于各类文本里的广泛运用引发了对于原创性以及真实性的关注…...
华泰证券2027届校招启动|提前批+国际管培+金融科技,三个专场一次说清
导读很多同学还在等“春招后半场捡漏”,但现实已经变了。头部企业的优质岗位,正在通过提前批 专项项目提前锁定人选。如果你现在才开始准备,很可能连入场资格都拿不到。这次华泰证券的校招,就是一个非常典型的信号:提…...
计算机毕业设计:Python汽车数据可视化分析平台 Django框架 可视化 线性回归 数据分析 机器学习 深度学习 AI 大模型(建议收藏)✅
博主介绍:✌全网粉丝50W,前互联网大厂软件研发、集结硕博英豪成立软件开发工作室,专注于计算机相关专业项目实战6年之久,累计开发项目作品上万套。凭借丰富的经验与专业实力,已帮助成千上万的学生顺利毕业,…...
C++资源控制哲学:从push_back与emplace_back看左值右值
一、从问题开始std::vector<Person> people; Person bob("bob", 22);people.push_back(bob); // 左值 people.push_back(Person("alice", 25)); // 右值 people.emplace_back("charlie", 30); // 直接构造为什么需要这么多插入…...
环模式饲料制粒机设计【农业机械】【论文+14张CAD图纸+proe三维+答辩稿】
环模式饲料制粒机作为农业机械领域的关键设备,其核心作用在于将粉状饲料原料通过物理挤压转化为颗粒状成品。这一过程不仅提升了饲料的适口性与营养保留率,更通过颗粒的规则形态减少了运输与储存过程中的粉尘损失,为规模化养殖提供了稳定高效…...
OpenFBX:轻量级FBX文件解析的终极解决方案
OpenFBX:轻量级FBX文件解析的终极解决方案 【免费下载链接】OpenFBX Lightweight open source FBX importer 项目地址: https://gitcode.com/gh_mirrors/op/OpenFBX OpenFBX是一款轻量级开源FBX导入工具,专为解决3D开发中FBX文件解析难题而设计。…...
打卡信奥刷题(3066)用C++实现信奥题 P6877 [JOI 2020 Final] 只不过是长的领带 / Just Long Neckties
P6877 [JOI 2020 Final] 只不过是长的领带 / Just Long Neckties 题目描述 JOI 公司发明了一种领带,一共有 N1N1N1 条领带,编号为 111 到 N1N1N1,第 iii 条领带的长度为 AiA_iAi。 JOI 公司开了一个派对,派对中有 NNN 名员工…...
