【初阶数据结构】实现顺序结构二叉树->堆(附源码)

文章目录

须知

💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力!

👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗?别忘了点赞、收藏并分享给更多的小伙伴哦!你们的支持是我不断进步的动力!
🚀 分享给更多人:如果你觉得这篇文章对你有帮助,欢迎分享给更多对数据结构感兴趣的朋友,让我们一起进步!

⼀般堆使⽤顺序结构的数组来存储数据,堆是⼀种特殊的⼆叉树,具有⼆叉树的特性的同时,还具备其他的特性。
 1.堆的概念与结构
如果有⼀个关键码的集合 K = { k 0 , k 1 , k 2 , ... k n −1 } ,把它的所有元素按完全⼆叉树的顺序存储⽅式存储,在⼀个⼀维数组中,并满⾜: K i <= K 2∗ i +1 K i >= K 2∗ i +1 K i <= K 2∗ i +2 ),i = 0、 1 2... ,则称为⼩堆(或⼤堆)。将根结点最⼤的堆叫做最⼤堆或⼤根堆,根结点最⼩的堆
叫做最⼩堆或⼩根堆。
1.1 堆的性质
堆中某个结点的值总是不⼤于或不⼩于其⽗结点的值;
堆总是⼀棵完全⼆叉树。
1.1.1 ⼆叉树性质
对于具有 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 否则⽆右孩⼦
2 堆的模拟实现
底层:使用数组,进行了特殊的处理成为堆。

下面将以 建立小堆为示例:

heap.h头文件下的函数声明和其它头文件

#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);

 测试文件:

#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函数的实现方法(重点

2.1 堆的初始化和销毁
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;
}
2.2 入堆操作
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;
}
2.2.1 向上调整算法

入堆之后,可能现在堆的数据不符合小堆或大堆的特性,需要从新调整堆的结构。

因此向上调整算法产生。

将新数据插⼊到数组的尾上,再进⾏向上调整算法,直到满⾜堆。
向上调整算法
先将元素插⼊到堆的末尾,即最后⼀个孩⼦之后
插⼊之后如果堆的性质遭到破坏,将新插⼊结点顺着其双双亲往上调整到合适位置即可

步骤(如下图)

代码如下:

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;}}	
}
2.3 堆的判空
// 判空
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}
2.4 出堆

将堆顶与最后一个数据交换,交换完成有效数据个数-1,在进行向下调整算法,因为可能删除后的数据结构不符合堆的特性。

出堆(删除数据):只能删除堆顶数据。

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);
}
 2.4.1 向下调整算法
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;}}
}

2.5 取堆顶数据

HPDataType HPTop(HP* php)
{assert(php && php->size);return php->arr[0];
}
2.6 获取堆有效数据个数
//获取堆中有效数据个数
size_t HPsize(HP* php)
{return php->size;
}

(附源码)

#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"void HpInit(HP* php)
{assert(php);php->arr = NULL;php->capacity = php->size = 0;
}void Hpdestroy(HP* php)
{assert(php);if (php->arr)free(php->arr);php->arr = NULL;php->capacity = php->size = 0;
}void swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}//时间复杂度logn
void AdjustUp(HpDataType* arr,int child)
{int parent = (child - 1) / 2;while (child>0){//if (arr[child] > arr[parent])//升序if (arr[child] < arr[parent])//降序{swap(&arr[child], &arr[parent]);child = parent;parent = (child - 1) / 2;}else {break;}}
}void AdjustDown(HpDataType* arr,int parent , int n)
{int child = 2 * parent + 1;//左孩子while (child < n){//if (child + 1 < n && arr[child] > arr[child + 1])//降序if (child + 1 < n && arr[child] < arr[child + 1])//升序->建大堆{child++;}if (arr[child] > arr[parent])//升序//if (arr[child] < arr[parent])//降序{swap(&arr[parent], &arr[child]);parent = child;child = 2 * parent + 1;}else{break;}}
}void HpPop(HP* php)//出堆:出的是堆顶的数据
{assert(php && php->arr);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 HoTop(HP* php)
{assert(php && php->size);return php->arr[0];
}void HpPush(HP* php, HpDataType x)
{assert(php);//扩容if (php->capacity == php->size){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_t HPsize(HP* php)
{return php->size;
}

相信通过这篇文章你对数据结构(堆)的有了初步的了解。如果此篇文章对你学习数据结构有帮助,期待你的三连,你的支持就是我创作的动力!!!

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

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

相关文章

ChatGPT变AI搜索引擎!以后还需要谷歌吗?

前言 在北京时间11月1日凌晨&#xff0c;正值ChatGPT两岁生日之际&#xff0c;OpenAI宣布推出最新的人工智能搜索体验&#xff01;具备实时网络功能&#xff01;与 Google 展开直接竞争。 ChatGPT搜索的推出标志着ChatGPT成功消除了即时信息这一最后的短板。 这项新功能可供 …

实用篇:Postman历史版本下载

postman历史版本下载步骤 1.官方历史版本发布信息 2.点进去1中的链接,往下滑动;选择你想要的版本 例如下载v11.18版本 3.根据操作系统选择 mac:mac系统postman下载 window:window系统postman下载 4.在old version里找到对应版本下载即可 先点击download 再点击free downlo…

提高后端接口性能的方法

个人bibilailai&#xff08;不喜请跳过&#xff09;&#xff1a;前几天参加的部门技术分享会&#xff0c;同事分享了一个内容为“提高接口性能的常见技巧”&#xff0c;个人觉得很有用&#xff0c;所以想在这里分享给大家&#xff0c;希望对刚入职场不久的兄弟姐妹们有所帮助。…

解决CentOS7 yum update异常:Could not retrieve mirrorlist

报错 Could not retrieve mirrorlist http://mirrorlist.centos.org/?release7&archx86_64&repoos&infrastock error was 14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Unknown error" 解决 执行命令&#xff1a;切换目录&#xff0…

Mybatis查询数据库,返回List集合,集合元素也是List。

#有时间需求会要求&#xff1a;查询全校的学生数据&#xff0c;且学生数据按班级划分。那么就需要List<List<user>>类型的数据。 SQL语句 SELECT JSON_ARRAYAGG(JSON_OBJECT(name , name ,BJMC, BJMC ,BJBH,BJBH)) as dev_user FROM dev_user WHERE project_id …

Linux:防火墙和selinux对服务的影响

1-1selinux 1-1 SELinux是对程序、文件等权限设置依据的一个内核模块。由于启动网络服务的也是程序&#xff0c;因此刚好也 是能够控制网络服务能否访问系统资源的一道关卡。 1-2 SELinux是通过MAC的方式来控制管理进程&#xff0c;它控制的主体是进程&#xff0c;而目标则是…

论文阅读笔记Dense Passage Retrieval for Open-Domain Question Answering

前言 在开放域的问答系统中&#xff0c;我们需要从大量的文本数据中搜索匹配我们想要的答案&#xff08;或者学习文档的“信息知识”用于生成答案&#xff09;&#xff0c;而对每个问题都进行全文的数据“学习”是不现实的&#xff0c;因此往往依赖于高效的文本检索来选择候选…

书生大模型第四期 | L0G3000 git 基础知识

1、破冰行动 fork项目 PR链接&#xff1a;跳转访问 https://github.com/InternLM/Tutorial/pull/21632、构建个人项目 创建一个仓库保存LLM学习的笔记&#xff0c;以md文件为主 博客页面项目

List 列表基础用法

List 列表基础用法 列表可以完成大多数集合类的数据结构实现。列表中元素的类型可以不相同&#xff0c;它支持数字&#xff0c;字符串甚至可以包含列表&#xff08;所谓嵌套&#xff09;。 列表是写在方括号 [] 之间、用逗号分隔开的元素列表。 和字符串一样&#xff0c;列表…

从0开始学PHP面向对象内容之(类,对象,构造/析构函数)

上期我们讲了面向对象的一些基本信息&#xff0c;这期让我们详细的了解一下 一、面向对象—类 1、PHP类的定义语法&#xff1a; <?php class className {var $var1;var $var2 "constant string";function classfunc ($arg1, $arg2) {[..]}[..] } ?>2、解…

详细记录555定时器组成和工作原理(第一篇)

目录 一、创作灵感 二、CB555的电路结构图 1、比较器C1和C2 2、三个5KΩ串联组成的分压电路 3、由与非门G1和G2组成的SR锁存器 4、G3、G4、集电极开路的放电三极管TD 三、CB555引脚功能 1、CB555引脚功能描述 2、CB555的功能表 四、CB555施密特触发器 1、施密特触发器…

Linux_02 Linux常用软件——vi、vim

vi编辑器有三种主要模式&#xff0c;每种模式的功能和用途不同&#xff1a; 一、命令模式 (Command Mode)&#xff1a; - 启动 vi 时默认进入此模式。 - 你可以在此模式下移动光标&#xff0c;输入各种命令&#xff08;如删除、复制、粘贴等&#xff09;。 yy&#xff1a;…

C#与C++交互开发系列(十八):跨进程通信之命名管道(Named Pipes)

1、前言 在 C# 和 C 应用程序之间进行数据交换时&#xff0c;命名管道&#xff08;Named Pipes&#xff09;是一种简单高效的进程间通信&#xff08;IPC&#xff09;方式。命名管道提供了可靠的双向通信通道&#xff0c;适合用于同一台机器上的跨进程通信。本文将深入介绍如何…

uniapp的video视频属性打包app后层级过高

问题&#xff1a;在使用uniapp开发APP时&#xff0c;使用video标签显示视频发现H5可以正常展示&#xff0c;但是打包到APP后&#xff0c;它的层级过高&#xff0c;把底部导航都盖住了。 官网说明&#xff1a;uni-app官网 官网给了cover-view组件或plus.nativeObj.view、subNVue…

【linux 多进程并发】0302 Linux下多进程模型的网络服务器架构设计,实时响应多客户端请求

0302 多进程网络服务器架构 ​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 一、概…

SQLI LABS | Less-26 GET-Error Based-All Your SPACES And COMMENTS Belong To Us

关注这个靶场的其它相关笔记&#xff1a;SQLI LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;过关流程 输入下面的链接进入靶场&#xff08;如果你的地址和我不一样&#xff0c;按照你本地的环境来&#xff09;&#xff1a; http://localhost/sqli-labs/Less-25/ 本关考察…

XML标记语言

最近在学XXE-XML外部实体注入漏洞时候&#xff0c;浅浅学习了一下XML&#xff0c;谨做此学习笔记。 目录 一&#xff1a;XML概述 二&#xff1a;XML语法 XML中的CDATA 三&#xff1a;使用PHP解析XML文档 添加节点 四&#xff1a;Xpath语言 绝对查找 相对查找 使用*匹配…

详解:模板设计模式

模板设计模式&#xff08;Template Pattern&#xff09;是一种行为设计模式&#xff0c;在软件设计中有着广泛的应用&#xff0c;旨在提高代码的可维护性和可复用性。 一、定义与特点 定义&#xff1a; 模板设计模式定义了一个算法的骨架&#xff0c;将某些步骤推迟到子类中实…

《向量数据库指南》——RAG质量评估与监控,打造高效AI引擎

嘿,各位向量数据库的小伙伴们,我是你们的老朋友王帅旭,大禹智库的向量数据库高级研究员,也是那本被大家津津乐道的《向量数据库指南》的作者。今天咱们来聊聊一个特别重要但又经常被忽视的话题——质量评估与监控,这可是确保咱们RAG(检索增强生成)系统稳定高效运行的关键…

Verilog HDL基础

模块的基本结构 module 模块名(端口列表); // 模块声明// 端口定义input [数据类型] [位宽] 输入端口列表; output [数据类型] [位宽] 输出端口列表; inout [数据类型] [位宽] 双向端口列表; // 数据类型定义wire [位宽] 线网名,线网名&#xff0c;…; …