二叉树顺序结构与堆的概念及性质(c语言实现堆)

上次介绍了树,二叉树的基本概念结构及性质:二叉树数据结构:深入了解二叉树的概念、特性与结构

今天带来的是:二叉树顺序结构与堆的概念及性质,还会用c语言来实现堆


文章目录

  • 1. 二叉树的顺序结构
  • 2.堆的概念和结构
  • 3.堆的实现(小堆)
    • 3.1项目文件规划
    • 3.2结构体和各功能一览(Heap.h)
    • 3.3重要函数详解(Heap.c)
      • 3.3.1堆向上调整算法
      • 3.3.2堆向下调整算法
    • 3.4各功能实现(Heap.c)
      • 初始化和销毁
      • 插入
      • 删除堆顶
      • 返回根(堆顶)的存储的数据
      • 节点数量
      • 是否为空
    • 3.5建堆时间复杂度


1. 二叉树的顺序结构

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。完全二叉树就比较适合使用顺序结构存储(数组)。现实中我们通常把(一种二叉树)使用顺序结构的数组来存储

注意:此堆非“彼堆”——操作系统虚拟进程地址空间中的堆。二者一个是一个是数据结构,一个是操作系统中管理内存的一块区域


2.堆的概念和结构

堆需要满足两点

  1. 堆是一个完全二叉树,即除了最底层,其他层都是完全填满,最底层从左到右填充
  2. 堆中的每个节点的值都必须大于等于(最大堆)或小于等于(最小堆)其子节点的值

根据节点值的大小关系,堆可以分为最大堆和最小堆。在最大堆中,根节点的值最大,每个节点的值都大于等于其子节点的值。在最小堆中,根节点的值最小,每个节点的值都小于等于其子节点的值

请添加图片描述

请添加图片描述


3.堆的实现(小堆)

3.1项目文件规划

请添加图片描述

  • 头文件Heap.h:用来基础准备(常量定义,typedef),链表表的基本框架,函数的声明
  • 源文件Heap.c:用来各种功能函数的具体实现
  • 源文件test.c:用来测试功能是否有问题,进行基本功能的使用

3.2结构体和各功能一览(Heap.h)

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);//返回根(堆顶)的存储的数据int HeapSize(HP* php);//堆的数据个数bool HeapEmpty(HP* php);//是否为空

3.3重要函数详解(Heap.c)

3.3.1堆向上调整算法

i位置节点的双亲序号:(i-1)/2

void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustUp(HPDataType* a, int child)//传入数组和下标索引
{int father = (child - 1) / 2;//利用公式来算出父亲节点下标while (child > 0){if (a[child] < a[father]){Swap(&a[child], &a[father]);//更新下标child = father;father = (father - 1) / 2;}else{break;//一旦符合小堆了,就直接退出}}
}

Swap 函数用于交换两个指针指向的值,而 AdjustUp 函数用于通过比较子节点与父节点并在有必要时交换它们来调整堆的结构,然后向上移动树,直到满足堆的性质

3.3.2堆向下调整算法

i位置的左孩子是 2 ∗ i + 1 2*i+1 2i+1,右孩子 2 ∗ i + 2 2*i+2 2i+2

void AdjustDown(HPDataType* a, int n, int father)
{int child = father * 2 + 1;//假设左孩子小  找出两者较小的来跟父节点比(大堆就找二者中较大的了)while (child < n){if (child + 1 < n && a[child] > a[child + 1]){child++;}if (a[child] < a[father]){Swap(&a[child], &a[father]);father = child;child = father * 2 + 1;}else{break;}}
}
  1. 给定一个数组 a,表示堆的结构,以及数组的大小 n 和要进行调整的父节点的索引 father
  2. 计算父节点的左孩子的索引为 father * 2 + 1
  3. 进入一个 while 循环,只要左孩子的索引小于 n (不会出数组)就会继续
  4. 在循环内部,首先检查右孩子是否存在且右孩子的值是否大于左孩子的值,如果是,则更新 child 为右孩子的索引。这是为了找出左右孩子中值较大的那个
  5. 比较左孩子的值和父节点的值,如果左孩子的值小于父节点的值,则调用 Swap 函数交换这两个索引处的值,并更新 fatherchild 的值,然后重新计算 child 的索引。这一步的目的是将较大的子节点值向上移动,以满足堆的性质
  6. 如果左孩子的值不小于父节点的值,则跳出循环,因为堆的性质已经满足

3.4各功能实现(Heap.c)

初始化和销毁

void HeapInit(HP* php)
{assert(php);php->a = NULL;php->size = php->capacity = 0;
}void HeapDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = php->capacity = 0;
}

插入

void HeapPush(HP* php, HPDataType x)
{assert(php);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 -1;}php->a = tmp;php->capacity = newCapacity;}//开始插入php->a[php->size] = x;php->size++;//要确保是小堆AdjustUp(php->a, php->size - 1);
}

删除堆顶

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

返回根(堆顶)的存储的数据

HPDataType HeapTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0];
}

节点数量

int HeapSize(HP* php)
{assert(php);return php->size;
}

是否为空

bool HeapEmpty(HP* php)
{assert(php);return php->size == 0;
}

3.5建堆时间复杂度

请添加图片描述

建堆的时间复杂度为O(N)


这次就到这里啦,下一次就利用这次的对来解决几个问题。感谢大家的支持!!!

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

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

相关文章

Vue : 监视属性

目录 一个案例 监听属性 handler immediate vm.$watch(xxx) 深度监视 监视的简写 computed和watch之间的区别 一个案例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport"…

使用TLS/SSL Pinning保护安卓应用程序

使用TLS/SSL Pinning保护安卓应用程序 在现代术语中&#xff0c;“SSL”&#xff08;安全套接层&#xff09;通常指的是“TLS”&#xff08;传输层安全&#xff09;。虽然 SSL 和 TLS 不是同一个东西&#xff0c;但 TLS 是 SSL 的改进和更安全的版本&#xff0c;并且在实践中已…

前后端分离nodejs+vue+ElementUi网上订餐系统69b9

课题主要分为两大模块&#xff1a;即管理员模块和用户模块&#xff0c;主要功能包括个人中心、用户管理、菜品类型管理、菜品信息管理、留言反馈、在线交流、系统管理、订单管理等&#xff1b; 运行软件:vscode 前端nodejsvueElementUi 语言 node.js 框架&#xff1a;Express/k…

超详细YOLOv8姿态检测全程概述:环境、训练、验证与预测详解

目录 yolov8导航 YOLOv8&#xff08;附带各种任务详细说明链接&#xff09; 搭建环境说明 不同版本模型性能对比 不同版本对比 参数解释 模型解释 训练 训练示意代码 训练数据与.yaml配置方法 .yaml配置 数据集路径 标签数据说明 训练参数说明 训练过程示意及输出…

集群部署篇--Redis 主从模式

文章目录 前言Redis 主从部署&#xff1a;1.1 主从架构 介绍&#xff1a;1.2 主从架构 实现&#xff1a;1.2.1 redis 安装&#xff1a; 1.3 主从架构优缺点&#xff1a;1.4 故障转移&#xff1a; 总结 前言 显然在线上环境中 Redis 服务不能以单机的方式运行&#xff0c;必须有…

PostgreSQL 作为向量数据库:入门和扩展

PostgreSQL 拥有丰富的扩展和解决方案生态系统&#xff0c;使我们能够将该数据库用于通用人工智能应用程序。本指南将引导您完成使用 PostgreSQL 作为向量数据库构建生成式 AI 应用程序所需的步骤。 我们将从pgvector 扩展开始&#xff0c;它使 Postgres 具有特定于向量数据库…

【C++】开源:fast-cpp-csv-parser数据解析库配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍fast-cpp-csv-parser数据解析库配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一…

C/C++学习笔记十三 C++中的重载运算符

1、什么是运算符重载&#xff1f; 运算符重载是 C 中的一项功能&#xff0c;使运算符&#xff08;例如 、- 等&#xff09;能够处理用户定义的数据类型。这种机制称为编译时多态性&#xff0c;并提供了为不同数据类型定制运算符行为的优点。 例如&#xff0c;我们可以重载“”运…

查看IOS游戏FPS

摘要 本篇技术博客将介绍如何使用克魔助手工具来查看iOS游戏的帧率&#xff08;FPS&#xff09;。通过克魔助手&#xff0c;开发者可以轻松监测游戏性能&#xff0c;以提升用户体验和游戏质量。 引言 在iOS游戏开发过程中&#xff0c;了解游戏的帧率对于优化游戏性能至关重要…

沙特电子签证照片尺寸要求及手机自拍制作方法介绍

Hey小伙伴们&#xff0c;准备去沙特阿拉伯旅行的朋友们注意啦&#xff01;沙特驻华大使馆对签证所需照片是有要求的&#xff0c;今天我要分享给大家的是关于沙特签证照片的尺寸和拍摄要求&#xff0c;让你的签证申请过程更加顺利哦&#xff01;此外&#xff0c;也教大家一种在家…

[Angular] 笔记 20:NgContent

chatgpt: 在Angular中&#xff0c;NgContent是用于内容投影&#xff08;Content Projection&#xff09;的一个重要概念。它允许你在一个组件中插入内容&#xff0c;并将这些内容投影到另一个组件中。 当你在一个组件中使用<ng-content></ng-content>标签时&…

redis 从0到1完整学习 (七):ZipList 数据结构

文章目录 1. 引言2. redis 源码下载3. zipList 数据结构3.1 整体3.2 entry 数据结构分析3.3 连锁更新 4. 参考 1. 引言 前情提要&#xff1a; 《redis 从0到1完整学习 &#xff08;一&#xff09;&#xff1a;安装&初识 redis》 《redis 从0到1完整学习 &#xff08;二&am…

Elasticsearch 查询命令执行时,如何通过词项索引、词项字典、倒排表定位文档逻辑介绍

这里不涉及到源码&#xff0c;只是根据网上的一些文章总结一下&#xff0c;目前不需要细究&#xff0c;只需要知道大概就好&#xff0c;除非你的工作是二次开发ES 一、​Term Index(词项索引)1、FSM&#xff08;Finite State Machine&#xff09;有限状态机2、FSA&#xff08;F…

海云安亮相2023北京国际金融安全论坛,助力金融企业数字化转型降本增效

近日&#xff0c;2023北京国际金融安全论坛暨金融科技标准认证生态大会在北京金融安全产业园成功举办。深圳海云安网络安全技术有限公司&#xff08;以下简称“海云安”&#xff09;受邀参展亮相此次大会。海云安作为国内领先的金融科技服务商&#xff0c;展示了开发安全系列产…

【北亚服务器数据恢复】san环境下LUN Mapping出错导致文件系统一致性出错的数据恢复案例

服务器数据恢复环境&#xff1a; san环境下的存储上一组由6块硬盘组建的RAID6&#xff0c;划分为若干LUN&#xff0c;MAP到跑不同业务的服务器上&#xff0c;服务器上层是SOLARIS操作系统UFS文件系统。 服务器故障&#xff1a; 业务需求需要增加一台服务器跑新增的应用&#xf…

Spring Boot:Spring Boot 入门、yaml 配置文件给属性赋值、自动装配原理详解

文章目录 Spring Boot - 01一、概述二、第一个 Spring Boot 程序补充知识 三、配置文件1. yaml 配置文件2. 使用 yaml 配置文件给属性赋值3. 松散绑定以及数据校验4. 配置文件的位置以及多环境配置 四、Spring Boot 分析1. pom.xml2. 启动器3. 主程序4. 自动装配原理5. 主启动类…

Kafka:本地设置

这是设置 Kafka 将数据从 Elasticsearch 发布到 Kafka 主题的三部分系列的第一部分;该主题将被 Neo4j 使用。第一部分帮助您在本地设置 Kafka。第二部分将讨论如何设置Elasticsearch将数据发布到Kafka主题。最后 将详细介绍如何使用连接器订阅主题并使用数据。 Kafka Kafka 是…

【Unity】【FBX】如何将FBX模型导入Unity

【背景】 网上能够找到不少不错的FBX模型资源&#xff0c;大大加速游戏开发时间。如何将这些FBX导入Unity呢&#xff1f; 【步骤】 打开Unity项目文件&#xff0c;进入场景。 点击Projects面板&#xff0c;右键选择Import New Assets 选中FBX文件后导入。Assets文件夹中就会…

【软件测试】为bug而生

为什么定位问题如此重要&#xff1f; 可以明确一个问题是不是真的“bug” 很多时候&#xff0c;我们找到了问题的原因&#xff0c;结果发现这根本不是bug。原因明确&#xff0c;误报就会降低多个系统交互&#xff0c;可以明确指出是哪个系统的缺陷&#xff0c;防止“踢皮球”&…

Apache Flink连载(二十一):Flink On Yarn运行原理-Yarn Application模式

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1. 任务提交命令