【初阶数据结构篇】实现顺序结构二叉树(堆的实现方法)

文章目录

  • 实现顺序结构二叉树(堆)
    • 前言
    • 代码位置
    • 堆的概念与结构
      • 概念
    • 堆的实现
      • 堆初始化和销毁
      • 堆的插入
      • 堆的判空
      • 堆的删除数据
      • 取堆顶数据

实现顺序结构二叉树(堆)

前言

​ ⼀般堆使⽤顺序结构的数组来存储数据,堆是⼀种特殊的⼆叉树,具有⼆叉树的特性的同时,还具备其他的特性


代码位置

[gitee](Heap/Heap · petrichor/2024-summer-c-language - 码云 - 开源中国 (gitee.com))

堆的概念与结构

概念

如果有⼀个关键码的集合 K = {k0 , k1 , k2, …,kn−1 },把它的所有元素按完全⼆叉树的顺序存储⽅式存储,在⼀个⼀维数组中,并满⾜: Ki<=K2i+1 且 Ki<=K2i+2(Ki >= K2i+1 且Ki >=K2i+2)( i = 0、1、2…) ,则称为⼩堆(或⼤堆)。将根结点最⼤的堆叫做最⼤堆或⼤根堆,根结点最⼩的堆叫做最⼩堆或⼩根堆。

1722170006545)

1722170006546)

堆具有以下性质

  • 堆中某个结点的值总是不⼤于或不⼩于其⽗结点的值;
  • 堆总是⼀棵完全⼆叉树。

完全二叉树性质

  • 对于具有 n 个结点的完全⼆叉树,如果按照从上⾄下从左⾄右的数组顺序对所有结点从 0 开始编号,则对于序号为 i 的结点有:
    1. 若 i>0 , i 位置结点的双亲序号: (i-1)/2 ; i=0 , i 为根结点编号,⽆双亲结点
    2. 若 2i+1<n,左孩⼦序号: 2i+1 , 2i+1>=n 则⽆左孩⼦
    3. 若 2i+2<n,右孩⼦序号: 2i+2 , 2i+2>=n 否则⽆右孩⼦

堆的实现

堆的底层结构为数组

本篇建小堆!!!大堆同理

Heap.h(其中方法会一一讲到)

  • 定义堆结构
  • 将存储数据类型重命名(方便之后替换->例如我们要求堆内存储char类型数据,只用改一行代码即可)
  • 所写的函数的声明,声明的时候参数只需要类型就可以了,名字加不加都一样
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>//定义堆的结构---数组typedef int HPDataType;typedef struct Heap
{HPDataType* arr;int size;//有效的数据个数int capacity;//空间大小
}HP;void HPInit(HP* php);
void HPDestroy(HP* php);void HPPush(HP* php, HPDataType x);
void HPPop(HP* php);HPDataType HPTop(HP* php);
// 判空
bool HPEmpty(HP* php);

test.c

  • 用来测试我们写的函数(函数的调用)

  • 这一部分就是自己写的时候用的测试用例,随便什么都行

最好是写一个方法测试一次,不然找错误的时候会很痛苦😜

#include"Heap.h"void test01()
{HP hp;HPInit(&hp);int arr[] = { 17,20,10,13,19,15 };for (int i = 0; i < 6; i++){HPPush(&hp, arr[i]);}//HPPop(&hp);while (!HPEmpty(&hp)){printf("%d ", HPTop(&hp));HPPop(&hp);}HPDestroy(&hp);
}int main()
{test01();return 0;
}

Heap.c

函数方法的实现,重点重点!!!

养成习惯,用assert宏来判断指针是否为空(避免使用时传入空指针,后续解引用都会报错)

堆初始化和销毁

void HPInit(HP* php)
{assert(php);php->arr = NULL;php->size = php->capacity = 0;
}void HPDestroy(HP* php)
{assert(php);if (php->arr)free(php->arr);php->arr = NULL;php->size = php->capacity = 0;
}

堆的插入

void HPPush(HP* php, HPDataType x)
{assert(php);//判断空间是否足够if (php->size == php->capacity){//扩容int newCapacity = php->capacity == 0 ? 4 : 2 * php->capacity;HPDataType* tmp = (HPDataType*)realloc(php->arr, newCapacity * sizeof(HPDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}php->arr = tmp;php->capacity = newCapacity;}php->arr[php->size] = x;AdjustUp(php->arr, php->size);++php->size;
}
  • 第一步,和顺序的插入一样,判断空间是否足够然后插入
  • 第二步,根据堆的特性实行向上调整算法
  • 注意传过去的参数是插入的位置,即插入前的size,在调整完后再将size++

向上调整算法

void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
void AdjustUp(HPDataType* arr,int child)
{int parent = (child - 1) / 2;while (child > 0)//不需要等于,child只要走到根节点的位置,根节点没有父节点不需要交换{if (arr[child] < arr[parent]){Swap(&arr[parent], &arr[child]);child = parent;parent = (child - 1) / 2;}else{break;}}	
}
  • 两个参数
    • 调整的堆
    • 孩子节点:即进行加一前的size
  • 利用父节点和孩子结点的关系

堆的判空

  • 和顺序表相同
// 判空
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

堆的删除数据

出堆:出的是栈顶的元素!!!

void HPPop(HP* php)
{assert(php && php->size);//arr[0]  arr[size-1]Swap(&php->arr[0], &php->arr[php->size - 1]);--php->size;AdjustDown(php->arr, 0, php->size);
}
  • 判断是否为空
  • 将堆顶数据与最后一个数据交换
  • 此时先将size–,因为向下调整是在数据有效数据个数中调整!

向下调整算法

void AdjustDown(HPDataType* arr, int parent, int n)
{int child = parent * 2 + 1;//左孩子//while (parent < n)while (child < n){//找左右孩子中找最小的if (child + 1 < n && arr[child] > arr[child + 1]){child++;}if (arr[child] < arr[parent]){Swap(&arr[child], &arr[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
  • 三个参数
    • 需要调整的堆(数组)
    • 父节点,因为出堆都是交换最后一个到栈顶,所以此处就是0
    • 数组有效数据个数,即size–
  • 循环结束条件:child<n(每次循环完后child都是parent*2+1,只要child不越界即可)
  • 在找左右孩子最小时,先要判断有没有右孩子

取堆顶数据

  • 也很简单,没什么好说的啦
HPDataType HPTop(HP* php)
{assert(php && php->size);return php->arr[0];
}

Heap.c(完整版)

#include"Heap.h"
void HPInit(HP* php)
{assert(php);php->arr = NULL;php->size = php->capacity = 0;
}
void HPDestroy(HP* php)
{assert(php);if (php->arr)free(php->arr);php->arr = NULL;php->size = php->capacity = 0;
}void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}void AdjustUp(HPDataType* arr,int child)
{int parent = (child - 1) / 2;while (child > 0)//不需要等于,child只要走到根节点的位置,根节点没有父节点不需要交换{if (arr[child] < arr[parent]){Swap(&arr[parent], &arr[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}void HPPush(HP* php, HPDataType x)
{assert(php);//判断空间是否足够if (php->size == php->capacity){//扩容int newCapacity = php->capacity == 0 ? 4 : 2 * php->capacity;HPDataType* tmp = (HPDataType*)realloc(php->arr, newCapacity * sizeof(HPDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}php->arr = tmp;php->capacity = newCapacity;}php->arr[php->size] = x;AdjustUp(php->arr, php->size);++php->size;
}void AdjustDown(HPDataType* arr, int parent, int n)
{int child = parent * 2 + 1;//左孩子//while (parent < n)while (child < n){//找左右孩子中找最小的if (child + 1 < n && arr[child] > arr[child + 1]){child++;}if (arr[child] < arr[parent]){Swap(&arr[child], &arr[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}void HPPop(HP* php)
{assert(php && php->size);//arr[0]  arr[size-1]Swap(&php->arr[0], &php->arr[php->size - 1]);--php->size;AdjustDown(php->arr, 0, php->size);
}
// 判空
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}
//取堆顶数据
HPDataType HPTop(HP* php)
{assert(php && php->size);return php->arr[0];
}

以上就是堆的实现方法啦,各位大佬有什么问题欢迎在评论区指正,您的支持是我创作的最大动力!❤️
请添加图片描述

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

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

相关文章

一键生成惊艳图像:使用Stable Diffusion打造惊人视觉效果

一、简介 Stable Diffusion是一种由Stability AI开发的生成式AI模型&#xff0c;能够将文本提示转换为高质量的图像。作为生成式扩散模型的一部分&#xff0c;Stable Diffusion通过解析和理解输入的文本提示&#xff0c;逐步生成与描述相匹配的图像。这一技术不仅在图像生成和…

MybatisPlus核心用法

MybatisPlus核心用法 目录 MybatisPlus核心用法1.使用MybatisPlus的基本步骤&#xff1a;2.MybatisPlus是如何获取实现CRUD的数据库表信息的&#xff1f;3.MybatisPlus的常用注解有哪些&#xff1f;如果表名称和实体类名称不符合约定该怎么做&#xff1f;IdType的常见类型有哪些…

漏洞复现-F6-11泛微-E-Cology-SQL

本文来自无问社区&#xff0c;更多漏洞信息可前往查看http://www.wwlib.cn/index.php/artread/artid/15575.html 0x01 产品简介 泛微协同管理应用平台e-cology是一套企业级大型协同管理平台 0x02 漏洞概述 该漏洞是由于泛微e-cology未对用户的输入进行有效的过滤&#xff0…

Skyeye云智能制造企业版源代码全部开放

智能制造一体化管理系统 [SpringBoot2 - 快速开发平台]&#xff0c;适用于制造业、建筑业、汽车行业、互联网、教育、政府机关等机构的管理。包含文件在线操作、工作日志、多班次考勤、CRM、ERP 进销存、项目管理、EHR、拖拽式生成问卷、日程、笔记、工作计划、行政办公、薪资模…

vue3 快速入门 (六) : vue中调用HTTP请求

1. 本文环境 Vue版本 : 3.4.29Node.js版本 : v20.15.0系统 : Windows11 64位IDE : VsCode 1.91.0 2. 访问HTTP 在Vue中&#xff0c;访问HTTP&#xff0c;可以使用axios第三方库。 axios 是一个基于 promise 的网络请求库&#xff0c;可以用于浏览器和 node.js。 axios使用简…

遗传算法与深度学习实战——进化深度学习

遗传算法与深度学习实战——进化深度学习 0. 前言1. 进化深度学习1.1 进化深度学习简介1.2 进化计算简介 2. 进化深度学习应用场景3. 深度学习优化3.1 优化网络体系结构 4. 通过自动机器学习进行优化4.1 自动机器学习简介4.2 AutoML 工具 5. 进化深度学习应用5.1 模型选择&…

【mybatis的批量操作】

在日常开发中&#xff0c;如果要操作数据库的话&#xff0c;或多或少都会遇到批量数据的处理&#xff0c;我们公司使用的mybaits-plus作为持久层的框架&#xff0c;今天就简单介绍一下mybaits批量操作数据库的几种方式。 1.循环插入 其实这种方式并不是批量插入&#xff0c;只…

功能实现——使用 OpenPDF 将 HTML 转换为 PDF,并将其上传到 FTP 服务器

目录 1.需求分析2.项目环境搭建3.将 HTML 转换为 PDF3.1.代码实现mail.htmlHtmlToPDFController.javaPDFConverterService.javaPDFConverterServiceImpl.java 3.2.测试3.3.注意事项 4.将生成的 PDF 上传到 FTP 服务器4.1.搭建 FTP 服务器4.2.配置文件4.3.代码实现FtpUtil.javaF…

谷粒商城实战笔记-75-商品服务-API-品牌管理-品牌分类关联与级联更新

文章目录 一&#xff0c;引入Mybatis Plus分页插件二&#xff0c;品牌列表的模糊查询三&#xff0c;增加品牌测试数据四&#xff0c;开发后台品牌关联分类接口1&#xff0c;接口product/categorybrandrelation/catelog/list2&#xff0c;接口product/categorybrandrelation/sav…

汽车长翅膀:GPU 是如何加速深度学习模型的训练和推理过程的?

编者按&#xff1a;深度学习的飞速发展离不开硬件技术的突破&#xff0c;而 GPU 的崛起无疑是其中最大的推力之一。但你是否曾好奇过&#xff0c;为何一行简单的“.to(‘cuda’)”代码就能让模型的训练速度突飞猛进&#xff1f;本文正是为解答这个疑问而作。 作者以独特的视角&…

数仓架构解析(第45天)

系列文章目录 经典数仓架构传统离线大数据架构 文章目录 系列文章目录烂橙子-终生成长群群主前言1. 经典数仓架构2. 传统离线大数据架构 烂橙子-终生成长群群主 前言 经典数仓架构 传统离线大数据架构 背景解析 1. 经典数仓架构 1991年&#xff0c;比尔恩门&#xff08;Bill…

牛客算法题解:数字统计、两个数组的交集、点击消除

目录 BC153 [NOIP2010]数字统计 ▐ 题解 NC313 两个数组的交集 ▐ 题解 AB5 点击消除 ▐ 题解 BC153 [NOIP2010]数字统计 题目描述&#xff1a; 题目链接&#xff1a; [NOIP2010]数字统计_牛客题霸_牛客网 (nowcoder.com) ▐ 题解 题目要求统计出某段数组中一共有多少个…

关于Buffer和Channel的注意事项和细节

1.举例 package org.example.demo;import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.util.RandomAccess;/*** MappedByteBuffer可…

动量参数(Momentum Parameter)

动量参数&#xff08;Momentum Parameter&#xff09;在机器学习中指的是一种用于加速梯度下降算法的技术&#xff0c;特别是深度学习中优化神经网络权重时。简单来说&#xff0c;动量参数是一种帮助优化过程加速并减少震荡的技术。 具体来说&#xff0c;动量参数具有以下特点…

网络编程——wireshark抓包、tcp粘包

目录 一、前言 1.1 什么是粘包 1.2 为什么UDP不会粘包 二、编写程序 文件树 客户端程序 服务器程序 tcp程序 头文件 makefile 三、 实验现象 四、改进实验 五、小作业 一、前言 最近在做网络芯片的驱动&#xff0c;验证功能的时候需要借助wireshark这个工具&…

猫头虎分享:Numpy知识点一文带你详细学习np.random.randn()

&#x1f42f; 猫头虎分享&#xff1a;Numpy知识点一文带你详细学习np.random.randn() 摘要 Numpy 是数据科学和机器学习领域中不可或缺的工具。在本篇文章中&#xff0c;我们将深入探讨 np.random.randn()&#xff0c;一个用于生成标准正态分布的强大函数。通过详细的代码示…

Android Studio 一键删除 Recent Projects信息的方法

Android Studio打开项目多了就一堆最近项目的记录&#xff0c;在IDE里面只能一个个手动删除。 File - Recent Projects 解决方案&#xff1a;修改配置文件 Note&#xff1a;方法不唯一。 Android Studio 存储了一个包含最近打开项目信息的配置文件。通过手动编辑或删除recentP…

科普文:kubernets原理

kubernetes 已经成为容器编排领域的王者&#xff0c;它是基于容器的集群编排引擎&#xff0c;具备扩展集群、滚动升级回滚、弹性伸缩、自动治愈、服务发现等多种特性能力。 本文将带着大家快速了解 kubernetes &#xff0c;了解我们谈论 kubernetes 都是在谈论什么。 一、背…

详细介绍BIO、NIO、IO多路复用(select、poll、epoll)

BIO、NIO、IO多路复用 BIO(Blocking IO)NIO(Non-blocking IO) 同步非阻塞IOIO多路复用selectpollepoll Redis的IO多路复用 BIO(Blocking IO) 最基础的IO模型&#xff0c;当进行IO操作时&#xff0c;线程会被阻塞&#xff0c;直到操作完成。 比如read和write&#xff0c;通常IO…

Python的输入规则

Python的输入特别有意思&#xff0c;它和C的输入不一样&#xff0c;它的输入的原型是类似于C的string类型&#xff0c;但是对于一些有意思的算法题来说&#xff0c;光是读入string型的内容并不容易解题&#xff0c;于是我们可以从两个方面来将输入给转化。 1. 先使用函数input…