二叉树——堆

news/2024/4/23 16:29:08/文章来源:https://blog.csdn.net/qq1053984219/article/details/129212761

一,树的概念及结构

1.树

4.结点的度:一个节点含有子树的个数称为该结点的度;如:A 的度为6.

5.叶节点或终端节点:度为0的节点称为叶节点;如:B

6.非终端结点或分支节点:度部位0的结点;如:D

7.双亲结点或父节点:若一个结点含有子节点,则这个节点称为其子节点的父节点;如:A是B的8.父节点。

8.孩子节点或子节点:一个结点含有的子树的根结点称为该节点的子节点;如:B是A的函子结点。

9.兄弟节点:具有相同的父结节点称为兄弟节点;如上图:B,C是兄弟节点。

10.树的度:一颗树中,最大使得节点称为树的度;如:上图树的度为6。

11.节点的层次:从根节点定义起,根为第一层,根的子节点为第二层,以此类推。

12.堂兄弟节点:双亲在同一层的节点互为堂兄弟。如:H,I互为堂兄弟。

13.节点的祖先:从根到该节点所经分支上的所有节点。如:A是所有节点的祖先。

14.子孙:以某节点为跟的子树中任意节点都称为该节点的子孙,如:所有的节点都是A的子孙。

15.森林:有m(m>0)棵互不相交的属的集合称为森林。

 2.二叉树

1.二叉树结点度最大为2。

2.二叉树子树左右次序不能颠倒,二叉树是有序树。

(1)满二叉树

二叉树的每层节点数都达到最大值。

(2)完全二叉树

二叉树深度为h,除第n层外,其他层的节点数都达到最大,而且h层所有的结点都集中在左层。

 (3)二叉树的性质

设根节点层数为1

1.非空二叉树i层最多有2^(n-1)个结点。

2.深度为h的二叉树最多有2^h -1个结点。

3.二叉树储存结构

1.顺序结构

用数组储存,物理上是数组,逻辑上是二叉树。

 2.链式储存

用链表表示二叉树,表的每个节点由数据和左右指针(对应左右孩子)组成,可以分为二叉链表和三叉链表。

 二叉链表                                        三叉链表

二叉树                        二叉链表                                三叉链表 

二,实现二叉树顺序结构

1.堆

        只有大堆和小堆

        堆是完全二叉树

2.实现堆

创建结构体

//创建小堆
typedef int HPDataType;//以数组的形式实现完全二叉树typedef struct Heap
{HPDataType* a;//创建指针数组size_t capacity;//容量size_t size;//大小
}HP;

初始化

类比顺序表

//初始化
void HPInit(HP* php)
{//断言,防止传递的指针为野指针assert(php);//初始化php->a = NULL;php->capacity = php->size = 0;
}

销毁堆

//销毁
void HPDestroy(HP* php)
{//断言assert(php);//释放申请的内存free(php->a);php->a = NULL;//置空php->capacity = php->size = 0;
}

插入数据

向上调整:先将数据插入到堆中,向上调整。找到子节点和这个子节点的父亲,比较大小。交换父亲和孩子结点的值,循环下去,child位于祖先结点时,循环结束。

void Swap(HPDataType* a, HPDataType* b)
{HPDataType tmp = *a;*a = *b;*b = tmp;
}void AdjustUp(HPDataType* a, size_t child)
{//找到子节点,以及这个孩子的父亲size_t parent = (child - 1) / 2;//比较父亲和孩子的大小while (child > 0){if (a[parent] > a[child]){Swap(&a[parent], &a[child]);}else{break;}child = parent;parent = (child - 1) / 2;}
}
//插入数据,保证堆还是小/大堆
void HPPush(HP* php, HPDataType x)
{//断言assert(php);//判断是否要扩容if (php->capacity == php->size){size_t newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;//realloc动态开辟空间HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newcapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);}else{php->a = tmp;php->capacity = newcapacity;}}//插入数据php->a[php->size] = x;php->size++;//向上调整堆,保证其还是一个小堆AdjustUp(php->a, php->size - 1);
}

打印“堆”

void HPPrint(HP* php)
{for (size_t i = 0; i < php->size; i++){printf("%d ", php->a[i]);}printf("\n");
}

删除堆顶的数据

将头结点和尾结点数据交换 然后size--,再向下调整。

AdjustDown(HPDataType* a, size_t size, size_t root)
{size_t parent = root;size_t child = parent * 2 + 1;//while (child < size){//找出孩子中较小的那一个,注意完全二叉树可能不存在右孩子//确定左右子树谁的值更小if (a[child] > a[child + 1] && child + 1 < size){//默认是左<右,这里是判断调整child++;}//如果孩子小于父亲就交换if (a[child] < a[parent]){Swap(&a[parent], &a[child]);}else{break;}//继续向下调整parent = child;child = parent * 2 + 1;}
}
void HPPop(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);
}

判断堆是否为空

size指向数组下一位 如果为空则是空

bool HPEmpty(HP* php)
{assert(php);//用表达式的返回值来判断,为0就为空return php->size == 0;
}

返回栈顶的值

size_t HPSize(HP* php)
{assert(php);//根据数组的性质,可直接返回size的值return php->size;
}

堆的大小

直接用size的值

HPDataType HPTop(HP* php)
{assert(php);//堆不为空assert(php->size > 0);return php->a[0];
}

堆排序

升序用大堆,降序用小堆。

以大堆为例

1.构造大堆,数组最大值就是根节点

2.顶端数与末尾数交换

3.反复执行2.

建造大堆:

首先将无序数组看做堆结构,按照综上到下,从左到右依次填入二叉树中。 

从最后一个非叶子结点即6,比较她左右节点较大值如果比6大就交换位置。

例如这里6和9需要交换。 

 找到下一个非叶子节点4重复上述步骤

 如此重复操作得到大堆 接下来进行排序

堆排序算法步骤

1.把无序数组构造成二叉树堆(以大堆为例)。

2.堆顶就是序列最大值,将堆顶与末尾元素交换,此时末尾就是最大值。

3.将剩余n-1个元素重新构造成一个堆,即重复1,2.

如此得到有序序列

堆排序不稳定

空间复杂度为O(1)

平均的时间复杂度为O(nlogn)

最坏情况下也稳定在O(nlogn) 

void HeapAdjust(int* arr, int start, int end)
{int tmp = arr[start];for (int i = 2 * start + 1; i <= end; i = i * 2 + 1){if (i < end&& arr[i] < arr[i + 1])//有右孩子并且左孩子小于右孩子{i++;}//i一定是左右孩子的最大值if (arr[i] > tmp){arr[start] = arr[i];start = i;}else{break;}}arr[start] = tmp;
}
void HeapSort(int* arr, int len)
{//第一次建立大根堆,从后往前依次调整for(int i=(len-1-1)/2;i>=0;i--){HeapAdjust(arr, i, len - 1);}//每次将根和待排序的最后一次交换,然后在调整int tmp;for (int i = 0; i < len - 1; i++){tmp = arr[0];arr[0] = arr[len - 1-i];arr[len - 1 - i] = tmp;HeapAdjust(arr, 0, len - 1-i- 1);}
}
int main()
{int arr[] = { 9,5,6,3,5,3,1,0,96,66 };HeapSort(arr, sizeof(arr) / sizeof(arr[0]));printf("排序后为:");for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){printf("%d ", arr[i]);}return 0;
}

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

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

相关文章

MySQL基础知识-刷题笔记

数据库刷题笔记 查漏补缺&#xff0c;面试八股文&#xff0c;以下内容未说明的均以MySQL数据库为准 where 不能和聚合函数一起使用 having可以和聚合函数一起使用 having必须与group by一起使用1、SUBSTRING_INDEX(str ,substr ,n)&#xff1a;返回字符substr在str中第n次出现位…

【强化学习】强化学习数学基础:贝尔曼公式

强化学习数学基础&#xff1a;贝尔曼公式强化学习的数学原理课程总览贝尔曼公式&#xff08;Bellman Equation&#xff09;一个示例状态值贝尔曼公式&#xff1a;推导过程贝尔曼公式&#xff1a;矩阵-向量形式&#xff08;Matrix-vector form&#xff09;贝尔曼公式&#xff1a…

基于合作型Stackerlberg博弈的考虑差别定价和风险管理的微网运行策略研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

从网易到支付宝,3年外包生涯做完,我这人生算是彻底废了......

我为什么一直做外包呢&#xff0c;原因是薪资和技术方面。 在华三做了一年外包&#xff0c;薪资5k&#xff0c;功能测试&#xff0c;接触Linux和网络&#xff0c;但是说实在的技术很难沉淀&#xff0c;就像雾里看花一样&#xff0c;过年之后&#xff0c;想走的人都走了&#x…

【vue2小知识】实现axios的二次封装

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;在vue2中实现axios的二次封装 目录 一、平常axios的请求发送方式 二、axios的一次封装…

造成android UI卡顿的原因及解决方法

Android 系统每隔 16ms 会发出 VSYNC 信号重绘界面(Activity)。之所以是 16ms&#xff0c;是因为 Android 设定的刷新率是 60FPS(Frame Per Second)&#xff0c;也就是每秒 60 帧的刷新率&#xff0c;约合 16ms 刷新一次。如果UI线程的执行时间超过16ms&#xff0c;则会产生丢帧…

【log】操作类日志处理 与 报错类日志处理logback

文章目录一、操作类日志处理【环绕增强】aop环绕增强导包第一步&#xff1a;自定义注解interface第二步&#xff1a;在Controller写一个测试的方法&#xff1a;第三步&#xff1a;编写LogAspect增强类与增强方法日志写入数据库&#xff08;使用mybatis&#xff09;第一步&#…

MyBatis快速开发

查询user表中的所有数据 步骤&#xff1a; 创建user表 打开Navicat&#xff0c;新建查询&#xff0c;将下面SQL代码复制粘贴并执行&#xff1a; create database mybatis; use mybatis;drop table if exists tb_user;create table tb_user(id int primary key auto_incremen…

Vue3电商项目实战-商品详情模块6【17-商品详情-标签页组件、18-商品详情-热榜组件、19-商品详情-详情组件、20-商品详情-注意事项组件】

文章目录17-商品详情-标签页组件18-商品详情-热榜组件19-商品详情-详情组件20-商品详情-注意事项组件17-商品详情-标签页组件 目的&#xff1a;实现商品详情组件和商品评价组件的切换 大致步骤&#xff1a; 完成基础的tab的导航布局完成tab标签页的切换样式效果使用动态组件完…

【Rust 日报】2023-2-24 Dioxus 0.3 发布,巨大的更新

ascii-d - 画ASCII示意图的工具Rust写的画ASCII示意图的工具。支持各大平台。程序员的最爱啊。https://github.com/huytd/ascii-d/raw/master/_meta/toolbar-final.gifDioxus 0.3 发布&#xff0c;巨大的更新Dioxus 是新出的与 Yew 类似的 Rust Web 前端框架&#xff08;为什么…

【华为OD机试模拟题】用 C++ 实现 - 最大相连男生数(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 货币单位换算(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 选座位(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 停车场最大距离(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 重组字符串(2023.Q1) 【华为OD机试模…

Java-多线程-增强篇-锁强化第3篇

Java集合框架中的锁 今天我们继续来学习锁 字符串操作中的锁 String是线程安全的&#xff0c;因为使用final修饰Stringbuilder 是线程不安全的&#xff0c;其方法没有使用synchronized修饰StringBuffer 是线程安全的&#xff0c;其方法使用synchronized修饰 List集合中的锁 …

内核并发消杀器(KCSAN)技术分析

一、KCSAN介绍KCSAN(Kernel Concurrency Sanitizer)是一种动态竞态检测器&#xff0c;它依赖于编译时插装&#xff0c;并使用基于观察点的采样方法来检测竞态&#xff0c;其主要目的是检测数据竞争。KCSAN是一种检测LKMM(Linux内核内存一致性模型)定义的数据竞争(data race)的工…

【网络原理8】HTTP请求篇

在上一篇文章当中&#xff0c;我们也提到了什么是HTTP。 每一个HTTP请求&#xff0c;都会对应一个HTTP响应。 下面这一篇文章&#xff0c;将聊一下HTTP请求的一些内容 目录 一、URL 第一部分&#xff1a;协议名称 第二部分:认证信息(新的版本已经没有了) 第三部分&#xf…

【数通网络交换基础梳理1】二层交换机、以太网帧、MAC地址详解及数据帧转发原理(爆炸细)

一、网络模型 万年不变&#xff0c;先从模型结构分析&#xff0c;现在大家熟知的网络模型有两种。第一种是&#xff0c;OSI七层模型&#xff0c;第二种是TCP/IP模型。在实际运用中&#xff0c;参考更多的是TCP/IP模型。 OSI七层模型 TCP/IP模型 不需要全部理解&#xff0c;…

Spring MVC 源码- HandlerExceptionResolver 组件

HandlerExceptionResolver 组件HandlerExceptionResolver 组件&#xff0c;处理器异常解析器&#xff0c;将处理器&#xff08; handler &#xff09;执行时发生的异常&#xff08;也就是处理请求&#xff0c;执行方法的过程中&#xff09;解析&#xff08;转换&#xff09;成对…

Python变量的定义和使用

定义&#xff1a;变量就是计算机内存中存储某些数据的位置的名称 形象理解变量就是一个存放东西的容器&#xff0c;该容器的名字就叫做变量&#xff0c;容器存放的东西就是变量的值 变量的组成&#xff1a; 标识&#xff1a;标识对象所储存的内存地址&#xff0c;使用内置函数i…

六千字让你明白什么是数字孪生?

文章目录1. 背景2. 数字孪生基础2.1 概念2.2 价值3. 技术生态3.1 技术体系3.2 核心技术3.2.1 多领域、多尺度融合建模3.2.2 数据驱动与物理模型融合的状态评估3.2.3 数据采集和传输3.2.4 全生命周期数据管理3.2.5 虚拟现实呈现3.2.6 高性能计算3.3 建设3.3.1 重点3.3.1.1 数字孪…

SEATA是什么?它的四种分布式事务模式

一、SEATA是什么&#xff1f; Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 在继续学习使用SEATA之前&#xff0c;对s…

数据结构栈的经典OJ题【leetcode最小栈问题大剖析】【leetcode有效的括号问题大剖析】

目录 0.前言 1.最小栈 1.1 原题展示 1.2 思路分析 1.2.1 场景引入 1.2.2 思路 1.3 代码实现 1.3.1 最小栈的删除 1.3.2 最小栈的插入 1.3.3 获取栈顶元素 1.3.4 获取当前栈的最小值 2. 有效的括号 0.前言 本篇博客已经把两个关于栈的OJ题分块&#xff0c;可以根据目…