二叉树(2)

 

目录

2.5 二叉树的存储结构

3.二叉树的顺序结构及实现

3.1二叉树的顺序结构

3.2堆的概念以及结构

3.3堆的实现

3.4堆的代码实现

3.5堆的应用


书接上回,我们继续学习二叉树的知识

2.5 二叉树的存储结构

二叉树一般可以使用两种数据结构,一种顺序结构,一种链式结构。

顺序储存

顺序结构存储就是使用 数组来存储,一般使用数组 只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲解。 二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

表示二叉树的值在数组位置中父子下标关系

parent = (child - 1) \ 2

leftchild = parent * 2 + 1

rightchild = parent * 2 + 2

由图可知:将非完全二叉树存储在数组中,会浪费很多的空间

链式存储

  • 二叉树的链式存储结构是指,用 链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,当前我们学习中一般都是二叉链,后面课程学到高阶数据结构如红黑树等会用到三叉链
typedef int BTDataType;
// 二叉链
struct BinaryTreeNode
{struct BinTreeNode* LeftChild;  // 指向当前节点左孩子struct BinTreeNode* RightChild; // 指向当前节点右孩子BTDataType data;            // 当前节点值域
}// 三叉链
struct BinaryTreeNode
{struct BinTreeNode* Parent; // 指向当前节点的双亲struct BinTreeNode* LeftChild;   // 指向当前节点左孩子struct BinTreeNode* RightChild;  // 指向当前节点右孩子BTDataType _data;             // 当前节点值域
};

这里作了解就可以了,后面高阶数据结构会用到

3.二叉树的顺序结构及实现

3.1二叉树的顺序结构

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。 现实中我们通常把堆 ( 一种二叉树 ) 使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统 虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

3.2堆的概念以及结构

3.3堆的实现

->1.堆向下调整算法

现在我们给出一个数组,逻辑上看做一颗完全二叉树,我们通过从根节点开始的向下调整算法可以把它调整成一个小堆/大堆。向下调整有一个前提:左右子树必须是一个堆,才能调整

int array[] = {27, 15, 19, 18, 28, 34, 65, 49, 25, 37, };

->2.堆向上调整算法

例:尾插一个10,再进行向上调整算法,直到满足堆,以小根堆为例

->3.堆的删除

删除堆是删除堆顶数据,将堆顶的数据和最后一个数据一换,然后删除最后一个数据,再向下调整算法

3.4堆的代码实现

堆需要实现的功能

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>typedef int HDataType;typedef struct Heap
{HDataType* a;int size;int capacity;
}Heap;//初始化
void HeapInit(Heap* ps);
//销毁堆
void HeapDestroy(Heap* ps);
//向堆插入数据
void HeapPush(Heap* ps, HDataType x);
//向上调整,以大根堆为例
void AdjustUp(HDataType* ps, int child);
//向下调整,以大根堆为例
void AdjustDown(Heap* hp, int n, int parent);
//判断是否有数据
bool HEmpty(Heap* hp);
//获取元素个数
int HeapSize(Heap* hp);
//获取堆头元素
HDataType HeapTop(Heap* hp);
//删除堆尾元素
void HeapPop(Heap* hp);

实现堆最核心的两段代码

1.向上调整

//向上调整,以大根堆为例
void AdjustUp(HDataType* a, int child)
{assert(a);int parent = (child - 1) / 2;while (child > 0){if (a[child] > a[parent]){swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

2.向下调整

//向下调整,以大根堆为例
void AdjustDown(HDataType* hp, int n, int parent)
{assert(hp);int child = parent * 2 + 1;while (child < n){if ((child + 1) < n && hp[child] < hp[child + 1]){++child;}if (hp[child] > hp[parent]){swap(&hp[child], &hp[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

其他代码

删除堆尾元素

//删除堆尾元素
void HeapPop(Heap* hp)
{assert(hp);assert(!HEmpty(hp));swap(&hp->a[0], &hp->a[hp->size - 1]);hp->size--;AdjustDown(hp->a, hp->size, 0);
}

这里为什么不使用挪动直接删除?

1.效率低

2.父子关系全乱了

如图

这里我们用的是另一种方法,来间接删除

1.效率高

2.父子关系没有很乱

//初始化
void HeapInit(Heap* hp)
{assert(hp);hp->a = (HDataType*)malloc(sizeof(HDataType) * 4);if (NULL == hp->a){perror("HeapInit::malloc");return;}hp->size = 0;hp->capacity = 4;
}//交换
void swap(HDataType* x, HDataType* y)
{HDataType tmp = *x;*x = *y;*y = tmp;
}//销毁堆
void HeapDestroy(Heap* hp)
{assert(hp);assert(!HEmpty(hp));free(hp->a);hp->a = NULL;hp->size = hp->capacity = 0;free(hp);hp = NULL;
}//向堆插入数据
void HeapPush(Heap* hp, HDataType x)
{assert(hp);if (hp->size == hp->capacity){HDataType* tmp = (HDataType*)realloc(hp->a, sizeof(HDataType) * hp->capacity * 2);if (NULL == tmp){perror("HeapPsuh::malloc");return;}hp->a = tmp;hp->capacity *= 2;}hp->a[hp->size] = x;hp->size++;AdjustUp(hp->a, hp->size-1);
}//获取堆头元素
HDataType HeapTop(Heap* hp)
{assert(hp);assert(!HEmpty(hp));return hp->a[0];
}//判断是否有数据
bool HEmpty(Heap* hp)
{assert(hp);return hp->size == 0;
}//获取元素个数
int HeapSize(Heap* hp)
{assert(hp);return hp->size;
}

功能测试:

#include "Heap.h"int main()
{Heap st;HeapInit(&st);HeapPush(&st, 21);HeapPush(&st, 32);HeapPush(&st, 3);HeapPush(&st, 42);HeapPush(&st, 15);HeapPush(&st, 3);HeapPush(&st, 5);int k = 0;scanf("%d", &k);while (!HEmpty(&st) && k--){printf("%d ", HeapTop(&st));HeapPop(&st);}printf("\n");return 0;
}

3.5堆的应用

堆排序,即:利用堆的思想来进行排序,总共分为两个步骤

1.建堆

  • 升序:建大堆
  • 降序:建小堆

升序为什么不建小堆?

如果排升序建的是小堆,根结点的数据是最小的,剩下的做堆,选次小的,与上面删除堆尾元素一样,这样做会导致后面父子关系全乱了,得重新排序

如图:

所以排升序,建大堆,反之,排降序,建小堆

2.利用堆删除的思想来进行排序

代码实现:

#define N 10//排升序建大堆
void Heap_Sort(int* a, int n)
{//建堆,向上调整建堆 时间复杂度为:O(N*logN)/*for (int i = 1; i < n; ++i){AdjustUp(a, i);}*///向下调整,建大堆比上面那个快一点,这个的实际复杂度为:O(N)for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}int end = n - 1;while(end > 1){swap(a[0], a[end]);AdjustDown(a, end, end - 1);--end;}}int main()
{    int a[N] = {2, 1, 5, 7, 6, 8, 0, 9, 4, 3};    Heap_Sort(a, 10);return 0;
}

测试结果:

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

AI绘画模型之:UNet、Imagen 与 DeepFloyd IF

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

2024西安铁一中集训DAY27 ---- 模拟赛((bfs,dp) + 整体二分 + 线段树合并 + (扫描线 + 线段树))

文章目录 前言时间安排及成绩题解A. 倒水&#xff08;bfs dp&#xff09;B. 让他们连通&#xff08;整体二分 按秩合并并查集 / kruskal重构树&#xff09;C. 通信网络&#xff08;线段树合并 二分&#xff09;D. 3SUM&#xff08;扫描线 线段树&#xff09; 前言 T1没做出…

基于STM32瑞士军刀--【FreeRTOS开发】学习笔记(四)|| 同步 / 互斥 / 通信方法简介

本文概念部分粘贴自韦东山老师同步与互斥。 韦东山老师《FreeRTOS入门与工程实践(基于DshanMCU-103)》书籍获取 同步&互斥概念 一句话理解同步与互斥&#xff1a;我等你用完厕所&#xff0c;我再用厕所。 什么叫同步&#xff1f;就是&#xff1a;哎哎哎&#xff0c;我正在…

Linux中进程通信之信号

信号 信号通信&#xff0c;其实就是内核向用户空间进程发送信号&#xff0c;只有内核才能发信号&#xff0c;用户空间进程不能发送信号。 关于信号指令的查看&#xff1a;kill -l 例如我们之前使用的kill -9 pid用于杀死一个进程 使用一个死循环 成功发送kill -9指令&#x…

键盘输入数据的过程

当我们在键盘中按下按键的时候&#xff0c;键盘会向我们的 CPU 发送硬件中断&#xff08;也就是给 CPU 特定的针脚发送信号&#xff09;&#xff0c;该硬件中断有着自己的中断号&#xff0c;然后 CPU 内的寄存器就会记录下该中断号&#xff0c;然后会在操作系统中的中断向量表&…

DNTRo

文章目录 AbstractMethodExperimentConclusioninnovation link code Abstract 本文旨在解决计算机视觉领域中微小物体检测的问题。由于图像数据中微小物体所占像素比例很小&#xff0c;因此精确地检测这些物体仍然是一个巨大的挑战。特别是在地理科学和遥感领域&#xff0c;高…

18现代循环神经网络—seq2seq与束搜索

1.序列到序列学习(seq2seq) 上图展示的是 DNA 转录,它也是一种序列到序列的学习机器翻译 seq2seq 最早是用来做机器翻译的,给定一个源句子,自动翻译成目标语言给定一个源语言的句子,自动翻译成目标语言机器翻译中的输入序列和输出序列都是长度可变的seq2seq seq2seq 指的…

AI+生命科学方向第一课【Datawhale AI夏令营】

[我是大佬的搬运工] 01 赛题背景解析 http://competition.sais.com.cn/competitionDetail/532230/format 翻译一下&#xff1a; mRNA&#xff1a;疾病基因 siRNA&#xff1a;药物基因 RNAi&#xff1a;药物基因作用于疾病基因的机制 我们要完成的任务&#xff1a;预测某类…

力扣高频SQL 50题(基础版)第二十六题

文章目录 力扣高频SQL 50题&#xff08;基础版&#xff09;第二十六题1667.修复表中的名字题目说明实现过程准备数据实现方式结果截图总结 力扣高频SQL 50题&#xff08;基础版&#xff09;第二十六题 1667.修复表中的名字 题目说明 表&#xff1a; Users ----------------…

货拉拉论文入选亚太消费者研究会议及亚太营销国际学术会议

近日,亚太消费者研究会议(AP-ACR)召开。本次会议上,货拉拉和香港中文大学合作就论文《Why Showing Multiple Options Simultaneously Makes Customers Less Picky》(《为什么同步显示多个选项会使消费者变得更不挑剔》)进行主题报告。此前,本篇论文也曾在第二届亚太营销国际学术…

【Docomo】优质 4G

https://www.docomo.ne.jp/area/premium_4g/?icidCRP_AREA_technology_to_CRP_AREA_premium_4g 优质 4G 移动通信速度超过千兆字节LTE加速的主要基础技术256QAM44 MIMO&#xff08;麦莫&#xff09; 移动通信速度超过千兆字节 从 2020 年 3 月起将提供高达 1.7Gbps 的接收速度…

IoTDB 入门教程 实战篇⑤——Python示例(开源)

文章目录 一、前文二、新建Python项目三、安装依赖四、示例源码五、参考 一、前文 IoTDB入门教程——导读 本文详细阐述了如何通过一个Python项目成功连接到IoTDB时序数据库&#xff0c;进而展示了如何向该数据库高效地写入数据以及执行精确的数据查询操作。 此示例旨在为读者提…

云计算实训16——关于web,http协议,https协议,apache,nginx的学习与认知

一、web基本概念和常识 1.Web Web 服务是动态的、可交互的、跨平台的和图形化的为⽤户提供的⼀种在互联⽹上浏览信息的服务。 2.web服务器&#xff08;web server&#xff09; 也称HTTP服务器&#xff08;HTTP server&#xff09;&#xff0c;主要有 Nginx、Apache、Tomcat 等。…

程序员学长 | 快速学会一个算法,ANN

本文来源公众号“程序员学长”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;快速学会一个算法&#xff0c;ANN 今天给大家分享一个强大的算法模型&#xff0c;ANN。 人工神经网络 (ANN) 是一种深度学习方法&#xff0c;源自人类…

5种IO模型简述

文章目录 前言什么是IO模型&#xff1f;阻塞IO非阻塞IO多路复用IO信号驱动IO异步IO 结语 前言 最近学netty&#xff0c;当然无法避免IO模型这部分知识。 我尽量用最简洁的语言来讲清楚这个东西。 什么是IO模型&#xff1f; 既然最近学netty&#xff0c;就拿它来举例子。 比如…

计算机网络必会面经

1.键入网址到网页显示&#xff0c;期间发生了什么 2.在TCP/IP网络模型中。TCP将数据进行分段后&#xff0c;为什么还需要IP层继续分片 3.详细说明tcp三次握手&#xff0c;为什么是三次&#xff0c;若每次握手丢了&#xff0c;解决办法是什么 4.详细说明tcp四次挥手&#xff…

【JS|第22期】深入理解跨域

日期&#xff1a;2024年7月6日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xff…

esp-idf-v5.1.1所有官方例程讲解(esp32、esp32-C2、esp32-S3)之 a2dp_sink 详解

目录 1. 获取ESP-IDF和示例代码 2. 导航到示例代码 3. 示例代码结构 4. 关键文件解析 main.c 初始化和配置: bt_app_core.c 和 bt_app_core.h bt_app_av.c 和 bt_app_av.h A2DP事件处理: AVRCP事件处理: bt_app_sink.c 和 bt_app_sink.h 5. 编译和烧录 6. 测试…

新一代打工人用什么电脑桌面提醒的备忘录比较好?

在这个为了生活而起早贪黑的时代&#xff0c;新一代的打工人每天都需要处理大量的工作和信息。为了提高工作效率&#xff0c;选择一款合适的电脑桌面备忘录工具显得尤为重要。那么&#xff0c;什么样的备忘录工具才是最适合我们的呢&#xff1f; 首先&#xff0c;我们需要的是…

【研发日记】Matlab/Simulink技能解锁(十一)——Stateflow中的en、du、ex应用对比

文章目录 前言 项目背景 en类型 du类型 ex类型 组合类型 分析和应用 总结 参考资料 前言 见《【研发日记】Matlab/Simulink技能解锁(六)——六种Simulink模型架构》 见《【研发日记】Matlab/Simulink技能解锁(七)——两种复数移相算法》 见《【研发日记】Matlab/Simul…