【C语音 || 数据结构】二叉树--堆

文章目录

    • 前言
        • 1.1 二叉树的概念
        • 1.2 满二叉树和完美二叉树
        • 1.3 堆的概念
        • 1.4 堆的性质
        • 1.4 堆的实现
          • 1.4.1堆的向上调整算法
          • 1.4.1堆的向下调整算法
          • 1.4.1堆的接口实现
          • 1.4.1.1堆的初始化
          • 1.4.1.2堆的销毁
          • 1.4.1.3堆的插入
          • 1.4.1.4堆的删除
          • 1.4.1.4堆的判空
          • 1.4.1.4 获取堆的数据个数

前言

二叉树是一种重要的数据结构,其中每个节点最多有两个子节点:左子节点和右子节点。它常用于实现搜索算法、排序算法、数据存储和图形表示等。二叉树具有递归性,可以通过遍历算法(如前序、中序、后序和层次遍历)来访问其节点。学习和理解二叉树对于掌握更复杂的数据结构和算法至关重要。

1.1 二叉树的概念

二叉树(Binary Tree)是一种特殊的树形数据结构,它的每个节点最多有两个子节点,通常被称为左子节点和右子节点,二叉树的子树有左右之分,其次序不能任意颠倒。

  1. 根节点(Root Node):二叉树的起始节点,它没有父节点,但可能有左子节点和右子节点。
  2. 父节点(Parent Node):对于每个节点(除根节点之外的节点),都有父节点,是一个具有子节点的节点。
  3. 左子节点(Left Child):对于每个节点,其左下方的节点称为其左子节点。
  4. 右子节点(Right Child):对于每个节点,其右下方的节点称为其右子节点。
  5. 叶子节点(Leaf Node):没有子节点的节点称为叶子节点。
  6. 非叶子节点(Non-Leaf Node):除了叶子节点以外的节点都称为非叶子节点。
  7. (Degree):节点的度是指该节点的子节点数量。在二叉树中,节点的度最大为2。
  8. 深度(Depth):从根节点到最远叶子节点的最长路径上的节点数称为二叉树的深度。
  9. 高度(Height):对于任意节点n,n的高度为从n到一片树叶的最长路径上的节点数。所有树叶的高度为0,根节点的高度就是树的高度。
1.2 满二叉树和完美二叉树

满二叉树(Full Binary Tree):除了叶子节点外,每一个节点都有左右两个子节点的二叉树称为满二叉树。

完全二叉树(Complete BinaryTree):完全二叉树从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充,其叶子结点必须靠左对齐,且不能有短,最后一层最少可以只有一个。

这不是一个完美二叉树
在这里插入图片描述

1.3 堆的概念

(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵 完全二叉树的 数组对象。 堆是非线性数据结构,相当于一维数组,有两个直接后继。

  • 大堆:父节点一定比子节点大,但是兄弟节点之间,不存在大小关系,堆的根节点是整个堆中最大的数
  • 小堆:父节点一定比子节点小,但是兄弟节点之间,不存在大小关系,堆的根节点是整个堆中最小的数

堆的父亲节点的下标和子节点的下标可以进行相互运算:

  • Parent = (Chlid - 1) / 2
  • Chlid = Parent / 2 - 1
1.4 堆的性质
  • 完美二叉树构成。

大堆:
在这里插入图片描述
小堆:
在这里插入图片描述

1.4 堆的实现
1.4.1堆的向上调整算法

给定一个数组,且这个堆是一个小堆,逻辑上看作是一种完美二叉树,需要传两个参数,一个数组,一个就是插入位置的节点在数组中的下标

  • 在数组的最后插入数据,开始进行向上调整算法。
  • 如果这个节点小于他的父亲节点,那就进行交换。
  • 如果这个节点大于他的父亲节点,那就结束向上调整。

这里给一组数据进行交换

int a[] = {10,15,56,25,30,70,5};

在这里插入图片描述
堆的向上调整算法代码实现:

void Swap(HPDataType* x,HPDataType* y)
{HPDataType tmp = *x;*x = *y;*y = tmp;
}
void AdjustUp(HPDataType* a, int child)
{int Parent = (child- 1) / 2;while (child> 0){if (a[Parent] > a[child]){Swap(&a[Parent], &a[child]);child = Parent;Parent = (child - 1) / 2;}else{break;}}
}
1.4.1堆的向下调整算法

给定一个数组,且这个堆是一个小堆,逻辑上看作是一种完美二叉树。然后我们从根节点开始向下调整,向下调整算法有一个前提:左右子树必须是一个堆,才能进行调整。然后计算出这个根节点的两个孩子节点,进行比较,哪个小,让其与根节点进行比较。这里需要传三个参数,第一个数组,第二个是数组的个数,第三个是根节点的下标

  • 如果根节点大于孩子节点,那就进行交换。
  • 如果根节点小于孩子节点,就停止交换。

这里给一组数据进行交换

int a[]= {}

在这里插入图片描述
堆的向下调整算法代码实现:

void Swap(HPDataType* x,HPDataType* y)
{HPDataType tmp = *x;*x = *y;*y = tmp;
}
void AdjustDown(HPDataType* a, int n, int Parent)
{// 这里可以使用假设法int child = Parent * 2 + 1;while (child < n){// 假设法这个位置需要进行判断是否是小的哪个孩子,不是则需要进行更新if (a[child] > a[child + 1] && child + 1 < n){child += 1;}if (a[Parent] > a[child]){Swap(&a[Parent], &a[child]);Parent = child;child = Parent * 2 + 1;}else{break;}}
}
1.4.1堆的接口实现
  • 堆的初始化(HeapInit):用于初始化堆结构,为堆的后续操作做好准备。
  • 堆的销毁(HeapDestroy):释放堆占用的资源,通常涉及删除堆中的所有元素和释放内存。
  • 堆的插入(HeapPush):向堆中插入一个新元素,并保持堆的性质(大堆或小堆)。
  • 堆的删除(HeapPop):删除堆顶数据,将堆顶数据和堆尾数据进行交换,并保持堆的性质(大堆或小堆)。
  • 获取堆顶数据(HeapTop):获取堆顶数据。
  • 堆的判空(HeapEmpty):判断堆是否是空。
  • 堆的数据个数(HeapSize):计算堆中的数据个数。
1.4.1.1堆的初始化

对于堆的这个结构体来说,可以给_a开空间,也可以不开,一会儿进行push的时候,会进行判断,所以就可以制空,以防止成为野指针。对于size,可以给-1,这样就刚刚好和下标对上了。

typedef int HPDataType;
typedef struct Heap
{HPDataType* _a;int _size;    // 堆顶的下一个位置的下标int _capacity;// 堆的空间
}Heap;
// 堆的初始化
void HeapInit(Heap* hp)
{assert(hp);hp->_a = NULL;hp->_capacity = hp->_size = 0;
}
1.4.1.2堆的销毁
void HeapDestroy(Heap* php)
{assert(php);free(php->_a);php->_a = NULL;php->_size = php->_capacity = 0;
}
1.4.1.3堆的插入

这里插入数据,需要插入到这个数组的最后一个位置,然后进行向上调整算法,让他始终保持这个小堆(大堆)。

void HeapPush(Heap* php,HPDataType x)
{assert(php);if (php->_capacity == php->_size){int newcapacity = php->_capacity == 0 ? 4 : php->_capacity * 2;HPDataType* new_a = (HPDataType*)realloc(php->_a,newcapacity*sizeof(HPDataType));if (new_a == NULL){perror("HeapPush()::realloc() fail!!");return;}php->_capacity = newcapacity ;php->_a = new_a;}php->_a[php->_size++] = x;AdjustUp(php->_a, hp->_size - 1);
}
1.4.1.4堆的删除

需要将堆中最后一个节点于整个堆的根节点进行交换,交换完成之后,直接删除最后一个下标的位置,在进行向下调整。

void HeapPop(Heap* php)
{assert(php && php->_size > 0);Swap(&php->_a[0],&php->_a[php->_size - 1]);php->_size--;AdjustDown(php->_a, php->_size, 0);
}
1.4.1.4堆的判空

因为结构体中的size就是用来记录堆的数据个数的,所以可以直接判断这个数是否等于0。

int HeapEmpty(Heap* php)
{assert(php);return php->_size == 0;
}
1.4.1.4 获取堆的数据个数

结构体中的size就是用来计数的,所以会方便很多

void HeapSize(Heap* php)
{assert(php);return php->_size;
}

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

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

相关文章

单体架构改造为微服务架构之痛点解析

1.微服务职责划分之痛 1.1 痛点描述 微服务的难点在于无法对一些特定职责进行清晰划分&#xff0c;比如某个特定职责应该归属于服务A还是服务B? 1.2 为服务划分原则的痛点 1.2.1 根据存放主要数据的服务所在进行划分 比如一个能根据商品ID找出商品信息的接口&#xff0c;把…

随手记:uniapp图片展示,剩余的堆叠

UI效果图&#xff1a; 实现思路&#xff1a; 循环图片数组&#xff0c;只展示几张宽度就为几张图片边距的宽度&#xff0c;剩下的图片直接堆叠展示 点击预览的时候传入当前的下标&#xff0c;如果是点击堆叠的话&#xff0c;下标从堆叠数量开始计算 <template><…

pycharm基本使用(常用快捷键)

0.下载 pycharm官网下载 选择合适的版本&#xff0c;本文以2024.1为例 1.简单应用 常用快捷键 ctrlD 复制当前行 ctrlY 删除当前行 ctrlX 剪切当前行&#xff08;可用作删除&#xff0c;更顺手&#xff09; shift↑ 选中多行ctrlshiftF10 运行 shiftF9 调试ctrl/ 注释当前…

数据结构入门:探索数据结构第一步

0.引言 在我们的日常生活中&#xff0c;经常需要管理大量的数据&#xff0c;就譬如学校中有好几千个学生&#xff0c;中国有十三亿人口&#xff0c;对于那么多的数据进行查找、插入、排序等操作就会比较慢。人们为了解决这些问题&#xff0c;提高对数据的管理效率&#xff0c;…

docker被封禁,怎么拉取镜像,打包所有镜像

因为docker被国内封禁了&#xff0c;所以我把电脑上之前的镜像全部打包出来了 你们也可以打包&#xff0c;我提供一个脚本&#xff0c;你运行即可 export_docker.sh #!/bin/bash# 导出目录 EXPORT_DIR"docker_images_backup" mkdir -p "$EXPORT_DIR"# 获…

Calibre版图验证工具调用_笔记

Siemens EDA Calibre版图验证工具调用 采用Cadence Virtuoso Layout Editor直接调用Siemens EDA Calibre工具需要进行文件设置&#xff0c; 在用户的根目录下&#xff0c;找到.cdsinit文件&#xff0c; 在文件的结尾处添加以下语句即可&#xff0c;其中&#xff0c;calibre.skl…

电表抄表软件是什么?

一、电表抄表软件的概念和作用 电表抄表软件&#xff0c;是一种致力于电力企业定制的数字化工具&#xff0c;用以远程控制搜集、管理方法与分析电表数据信息。它取代了传统人工抄表方法&#xff0c;大大提高了工作效率&#xff0c;降低了人为失误&#xff0c;并且能实时监控系…

flask基础3-蓝图-cookie-钩函数-flask上下文-异常处理

目录 一&#xff1a;蓝图 1.蓝图介绍 2.使用步骤 3.蓝图中的静态资源和模板 二.cookie和session 1.cookie 2.flask中操作cookie 3.session 4.session操作步骤 三.请求钩子 四.flask上下文 1.介绍 2.请求上下文&#xff1a; 3.应用上下文 3.g对象 五&#xff1a;…

【Linux】进程控制2——进程等待(waitwaitpid)

1. 进程等待必要性 我们知道&#xff0c;子进程退出&#xff0c;父进程如果不管不顾&#xff0c;就可能造成"僵尸进程”的问题&#xff0c;进而造成内存泄漏。另外&#xff0c;进程一旦变成僵尸状态&#xff0c;那就刀枪不入&#xff0c;“杀人不眨眼”的kill -9 也无能为…

香港户口需要什么条件?有学历要求吗?最新香港落户途径详解!

香港户口需要什么条件&#xff1f;有学历要求吗&#xff1f;最新香港落户途径详解&#xff01; 由于香港放开“落户”窗口&#xff0c;想去香港发展或者想拿香港身份的朋友都想抓住这个机会赶紧申请。 只是&#xff0c;香港户口办理是有条件的&#xff0c;而且有学历要求&…

VScode中连接并使用docker容器

前提条件&#xff1a; 1.在windows下安装Docker Desktop(方法可见下面的教程) Docker Desktop 安装使用教程-CSDN博客 2.在vscode安装3个必备的插件 3.先在ubuntu中把docker构建然后运行 4.打开vscode&#xff0c;按下图顺序操作 调试好之后上传到git上&#xff0c;然后后面…

《人人都是产品经理》笔记1:什么是产品?怎么入行?

《人人都是产品经理》笔记1&#xff1a;什么是产品&#xff1f;怎么入行&#xff1f; 产品是什么&#xff1f;产品经理、产品管理&#xff1f;真的想做产品经理吗&#xff1f;全书结构示意图 从写这篇文章开始&#xff0c;是个人第二次对该书进行阅读&#xff0c;在此进行个人的…

[Python学习篇] Python输入

关键字 input 语法&#xff1a;input("提示信息") 特点 当程序执行到input&#xff0c;等待用户输入&#xff0c;输入完成之后才能继续向下执行。input接收用户输入后&#xff0c;一般存储到变量中&#xff0c;方便使用。input会把接收到的任意用户输入的数据都当做…

老杨说运维 | 基于数据驱动的智观能力建设(文末附现场视频)

本期回顾来自擎创科技创始人兼CEO杨辰的现场演讲 青城山脚下的滔滔江水奔涌而过&#xff0c;承载着擎创一往无前的势头&#xff0c;共同去向未来。2024年6月&#xff0c;双态IT成都用户大会擎创科技“数智化可观测赋能双态运维”专场迎来了完满的收尾。 “没有2200年前李冰率众…

Java集合自测题

文章目录 一、说说 List , Set , Map 三者的区别&#xff1f;二、List , Set , Map 在 Java 中分别由哪些对应的实现类&#xff1f;底层的数据结构&#xff1f;三、有哪些集合是线程不安全的&#xff1f;怎么解决呢&#xff1f;四、HashMap 查询&#xff0c;删除的时间复杂度五…

word怎么单页横向设置(页码不连续版)

打开word&#xff0c;将光标放在第一页的最后位置。 然后点击布局下的分隔符&#xff0c;选择下一页。 将光标放在第二页的开头&#xff0c;点击布局下的纸张方向&#xff0c;选择横向即可。 效果展示。 PS&#xff1a;如果那一页夹在两页中间&#xff0c;那么在…

Python发送Outlook邮件的步骤流程有哪些?

Python发送Outlook邮件的技巧&#xff1f;如何使用Python发信&#xff1f; 在Python中使用SMTP协议发送邮件到Outlook邮箱是一项常见的任务。AokSend将介绍如何通过Python编程语言实现这一过程&#xff0c;从准备工作到实际发送邮件的具体步骤。 Python发送Outlook邮件&#…

构建汛期智慧水利新生态:EasyCVR视频汇聚监控综合管理方案解析

一、项目背景与目标 随着我国水利事业的不断发展&#xff0c;水利设施的管理与维护工作愈发重要。随着夏季汛期的到来&#xff0c;水利管理工作面临着巨大的挑战。为确保水利设施的安全运行&#xff0c;及时应对可能出现的汛情&#xff0c;建设一套高效、智能的视频监控可视化…

wms海外仓系统排名分析:哪个才更适合中小海外仓

对中小型海外仓来说&#xff0c;想在竞争激烈的市场下生存&#xff0c;关键就在于是否能改变自己落后的仓储管理模式&#xff0c;提升客户满意度和业务流畅度。 wms海外仓系统作为这一领域的关键工具&#xff0c;可以说在很大程度上决定了海外仓的业务标准化程度发展。不过现在…

MFC为什么说文档在数据的保存和给用户提供数据之间划分了清晰的界限?

MFC MFC&#xff08;Microsoft Foundation Classes&#xff09;是微软为Windows应用程序开发提供的一套C类库&#xff0c;它在设计上强调了"文档-视图"&#xff08;Document-View&#xff09;架构。这种架构将文档&#xff08;Document&#xff09;与用户界面&#…