【数据结构与算法】二叉树的综合运用

目录

一,层序遍历算法

1-1,队列结构的设立

1-2,逻辑分析

二,判断单值二叉树

三,求二叉树的最大深度


一,层序遍历算法

        二叉树的层序遍历是一层一层的从左到右遍历,现在问题是二叉树不支持随机访问,因此,我们需要借助其它结构来实现这一功能。通常,对于这种遍历算法我们要借助队结构的概念。

        补充:树的层序遍历也叫做广度优先遍历,而广度优先遍历通常要借助队列的结构实现。

1-1,队列结构的设立

        队列的结构相信大家都已非常熟悉了,如果队列结构不清楚的可以观看本人以前讲解队列的文章,本文在这里就不做过多说明了。我们可定义一个头文件,将队列的基础算法写进去,其中,要注意的是队列中的元素是树中的结点,因为往队列中装数据装的是树的结点,不可直接装树结点的数据,否则设置此结构几乎没用,下文分析时会详细说明,在这里我们只需先构造队列中的基础算法即可。如下:

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef struct Tree DataType;
typedef struct Node {DataType* val;struct Node* next;
}Node;
typedef struct Queue {Node* head;Node* tail;
}Queue;
void QueueInit(Queue* Q) {Q->head = Q->tail = 0;
}
void QueuePush(Queue* Q, DataType* x) {Node* node = (Node*)malloc(sizeof(Node));if (!node) {return;}node->val = x;node->next = 0;if (!Q->head) {Q->head = Q->tail = node;}else {Q->tail->next = node;Q->tail = node;}
}
void QueuePop(Queue* Q) {if (!Q->head) {return;}Node* node = Q->head->next;free(Q->head);Q->head = node;
}
bool QueueEmpty(Queue* Q) {return Q->head == NULL;
}
void QueueDestroy(Queue* Q) {if (!Q->head) {return;}Node* node = Q->head->next;while (Q->head != Q->tail) {free(Q->head);Q->head = node;node = node->next;}free(Q->head);free(Q);
}
1-2,逻辑分析

        队列结构设置完后,我们要考虑的是如何将每一层的数据从左到右放入队列中。如果直接将树结点中的数据直接导入,很显然,这跟用不用队列结构没多大关系,相当于直接层序遍历二叉树。因此,我们要考虑将树中结点导入,然后,利用结点间相连问题进行层序导入队列中。具体步骤和说明如下:

        首先,要将根结点导入队列,然后输出队列中首结点的数据,并先将此结点的左孩子导入进队列,再将右孩子导入进队列,最后删除首结点,以此类推,不断进行循环,当队列为空时相当于已层序遍历完整个二叉树。至于原因是因为我们输出首结点的元素后删除了首结点,所以当进行下一次循环将首结点的左右孩子导入时,相当于从树的下一层开始,从左到右导入数据。

代码如下:

void LevelOrder(Tree* root) {//空树直接退出if (!root) {return;}//建立队列结构Queue* Q = (Queue*)malloc(sizeof(Queue));QueueInit(Q);//先把根结点推入进去QueuePush(Q, root);//进行遍历,先将数据输出,导入队列左右孩子后要出队,即删除,当队为空时已遍历完。while (!QueueEmpty(Q)) {fprintf(stdout, "%d ", Q->head->val->val);if (Q->head->val->leftchild) {QueuePush(Q, Q->head->val->leftchild);}if (Q->head->val->rightchild) {QueuePush(Q, Q->head->val->rightchild);}QueuePop(Q);}
}

算法演示:

//设定队列结构和必要的头文件
#include "Queue.h"
typedef struct Tree {int val;//数据struct Tree* leftchild;//左孩子结点struct Tree* rightchild;//右孩子结点
}Tree;
//创建二叉树数据为x的结点
Tree* CreatNode(int x) {Tree* node = (Tree*)malloc(sizeof(Tree));node->val = x;node->leftchild = 0;node->rightchild = 0;return node;
}
//二叉树的销毁
void TreeDestroy(Tree* root) {if (!root) {return;}TreeDestroy(root->leftchild);TreeDestroy(root->rightchild);free(root);
}
//层序遍历算法(广度优先遍历)
void LevelOrder(Tree* root) {//空树直接退出if (!root) {return;}//建立队列结构Queue* Q = (Queue*)malloc(sizeof(Queue));QueueInit(Q);//先把根结点推入进去QueuePush(Q, root);//进行遍历,先将数据输出,导入队列左右孩子后要出队,即删除,当队为空时已遍历完。while (!QueueEmpty(Q)) {fprintf(stdout, "%d ", Q->head->val->val);if (Q->head->val->leftchild) {QueuePush(Q, Q->head->val->leftchild);}if (Q->head->val->rightchild) {QueuePush(Q, Q->head->val->rightchild);}QueuePop(Q);}
}
int main()
{//手动构建二叉树Tree* node1 = CreatNode(1);Tree* node2 = CreatNode(2);Tree* node3 = CreatNode(3);Tree* node4 = CreatNode(4);Tree* node5 = CreatNode(5);Tree* node6 = CreatNode(6);Tree* node7 = CreatNode(7);Tree* node8 = CreatNode(8);Tree* node9 = CreatNode(9);Tree* node10 = CreatNode(10);Tree* node11 = CreatNode(11);Tree* node12 = CreatNode(12);Tree* node13 = CreatNode(13);Tree* node14 = CreatNode(14);Tree* node15 = CreatNode(15);//结点的连接node1->leftchild = node2;node1->rightchild = node4;node2->leftchild = node3;node4->leftchild = node5;node4->rightchild = node6;node2->rightchild = node7;node3->leftchild = node8;node3->rightchild = node9;node7->leftchild = node10;node7->rightchild = node11;node5->leftchild = node12;node5->rightchild = node13;node6->leftchild = node14;node6->rightchild = node15;LevelOrder(node1);TreeDestroy(node1);return 0;
}

接下来我们用经典题型来进行解说二叉树的运用。

二,判断单值二叉树

单值二叉树:二叉树的每个结点都具有相同的值。

分析:

        我们可遍历二叉树,并且每一个节点值都和根节点的值进行比对,如果不等于根节点的值,则不是单值树。

代码如下:

/**以下是二叉树的结构式* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/bool JudgeTree(struct TreeNode* root, int x) {if (!root) {return true;} if (root->val != x) {return false;}//当有一个不满足条件时,一直返回的是false,最终结果也是false  return JudgeTree(root->left, x) && JudgeTree(root->right, x);
}bool isUnivalTree(struct TreeNode* root) {if (!root) {return true;}return JudgeTree(root, root->val);
}

举一反三:

        当我们遇到像bool类型的二叉树算法时,可以像上述题型一样,系统给定函数的类型和参数与我们遍历思路不同时,可再创建一个返回类型和参数都令我们"满意的函数"。如以上题中系统给定的函数是bool isUnivalTree(struct TreeNode* root),参数令我们不满意,我们可创建一个函数:bool JudgeTree(struct TreeNode* root, int x),有个参数x以便后面我们比较。

        还有,像bool类型的函数一般不好在其中递归遍历,所以,当递归遍历时经常在返回值中运用

逻辑运算符连接遍历。如以上题中return JudgeTree(root->left, x) && JudgeTree(root->right, x)。在此函数中用"&&"符号连接进行遍历。


三,求二叉树的最大深度

题解:二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数。

分析:

        显然,本题也需要我们运用二叉树基础算法中的遍历算法。求解最大深度,我们可在递归遍历时记录在此函数中,以root为根结点左右孩子的总共数量,大的一方就是以此函数中root为根结点的子二叉树的最大深度,即当最终返回时,返回的是二叉树的最大深度。

代码如下:

/** * 二叉树的结构* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/int maxDepth(struct TreeNode* root){if (!root) {return 0;}//记录左孩子的数量int leftsize = maxDepth(root->left) + 1;//记录右孩子的数量int rightsize = maxDepth(root->right) + 1;//返回以此递归函数中的子二叉树的最大深度return (leftsize > rightsize) ? leftsize : rightsize;
}

        对于本题没有什么好扩充的知识,讲解此题的目的是让我们更好的运用递归,理清其中的逻辑,该如何控制递归的走向。


学习建议:二叉树的运用是建立在二叉树基础算法之上,在学习到这一方面,必须要把二叉树的基本算法理解明白之后再上手。否则根基不稳后面会很吃亏。

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

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

相关文章

我们距离“裸眼3D自由”,还有多远?

还记得2018年&#xff0c;我曾熬夜好几天&#xff0c;就为了抢一张故宫博物院“清明上河图互动艺术展演”的门票。 后来&#xff0c;我也曾去过很多城市&#xff0c;看过不少策划精良的展览。那场“穿越北宋”的名画之旅&#xff0c;依然是我看过的&#xff0c;最具沉浸感的一场…

【Linux】kill 命令使用

经常用kill -9 XXX 。一直在kill&#xff0c;除了kill -9 -15 &#xff0c;还能做什么&#xff1f;今天咱们一起学习一下。 kill 命令用于删除执行中的程序或工作。 kill命令 -Linux手册页 命令选项及作用 执行令 man kill 执行命令结果 参数 -l 信号&#xff0c;若果…

力扣学习笔记——49. 字母异位词分组

49. 字母异位词分组 https://leetcode.cn/problems/group-anagrams/?envTypestudy-plan-v2&envIdtop-100-liked 给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。…

驱动开发5 阻塞IO实例、IO多路复用

1 阻塞IO 进程1 #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <string.h>int main(int argc, char co…

Luckyexcel 加载 springboot 后台返回的 excel 文件并显示

&#x1f451; 博主简介&#xff1a;知名开发工程师 &#x1f463; 出没地点&#xff1a;北京 &#x1f48a; 2023年目标&#xff1a;成为一个大佬 ——————————————————————————————————————————— 版权声明&#xff1a;本文为原创文…

Unity - 导出的FBX模型,无法将 vector4 保存在 uv 中(使用 Unity Mesh 保存即可)

文章目录 目的问题解决方案验证保存为 Unity Mesh 结果 - OK保存为 *.obj 文件结果 - not OK&#xff0c;但是可以 DIY importer注意References 目的 备忘&#xff0c;便于日后自己索引 问题 为了学习了解大厂项目的效果&#xff1a; 上周为了将 王者荣耀的 杨玉环 的某个皮肤…

关于nacos的配置获取失败及服务发现问题的排坑记录

nacos配置更新未能获取到导致启动报错 排查思路&#xff1a; 1、是否添加了nacos的启动pom依赖 参考&#xff1a; <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><…

vue3中的route和router

因为我们在 setup 里面没有访问 this&#xff0c;所以我们不能再直接访问 this.$router 或 this.$route。作为替代&#xff0c;我们使用 useRouter 和useRoute函数,或者 Vue3 中提供了一个 getCurrentInstance 方法来获取当前 Vue 实例 <script setup>import { useRoute…

GEE图表——利用NOAA气象数据绘制气温预测图

简介 气象预测是通过气象数据和模型对未来某一时间和地点的天气情况进行预测。 具体步骤如下&#xff1a; 1. 数据采集&#xff1a;从气象观测站、卫星等获取气象数据&#xff0c;包括气压、水汽、风速、温度、降雨、云量等。 2. 数据清洗&#xff1a;对采集到的数据进行质…

学到一招 chrome 浏览器 debug 悬浮样式

前言 今天在想调试一个开源 UI 框架的某个table row的隔行换色的样式设置&#xff0c;发现这个颜色只有鼠标悬浮在row的时候才能拿到&#xff0c;但是想要拷贝 row 样式&#xff0c;鼠标必须离开悬浮区域&#xff0c;去chrome的debug控制台内才能拷贝&#xff0c;但是一离开悬…

Qt之设置QLineEdit只能输入浮点数

Qt提供了QDoubleValidator来进行浮点数校验,但是它同样存在限定范围无效的问题,详见:Qt之彻底解决QSpinBox限定范围无效的问题 因此我们要子类化QDoubleValidator,并重写其中的validate方法,最后调用QLineEdit的setValidator方法,并将这个子类当做参数传入。 QHDoubleVa…

怎么降低Linux内核驱动开发的风险?

降低Linux内核驱动开发的风险是一个重要的目标&#xff0c;因为内核驱动开发可能会对系统的稳定性和安全性产生重要影响。以下是一些降低风险的建议&#xff1a; 1. 深入了解Linux内核&#xff1a;在开始内核驱动开发之前&#xff0c;建议深入学习Linux内核的工作原理和架构&a…

[Unity]将所有 TGA、TIFF、PSD 和 BMP(可自定义)纹理转换为 PNG,以减小项目大小,而不会在 Unity 中造成任何质量损失

如何使用 只需在“项目”窗口中创建一个名为“编辑器”的文件夹&#xff0c;然后在其中添加此脚本即可。然后&#xff0c;打开窗口-Convert Textures to PNG&#xff0c;配置参数并点击“Convert to PNG&#xff01; ”。 就我而言&#xff0c;它已将某些 3D 资源的总文件大小…

交互式 Web 应用 0 基础入门

初探 Gradio&#xff1a;轻松构建交互式 Web 应用 文章目录 初探 Gradio&#xff1a;轻松构建交互式 Web 应用Why Gradio?安装 Gradio创建交互式界面1. gr.Interface2. gr.Blocks 强大的组件库输入输出组件控制组件布局组件 示例交互式数据可视化多组件同时&#xff08;嵌套&a…

vue3 源码解析(1)— reactive 响应式实现

前言 本文是 vue3 源码解析系列的第一篇文章&#xff0c;项目代码的整体实现是参考了 v3.2.10 版本&#xff0c;项目整体架构可以参考之前我写过的文章 rollup 实现多模块打包。话不多说&#xff0c;让我们通过一个简单例子开始这个系列的文章。 举个例子 <!DOCTYPE html…

电力通信与泛在电力物联网技术的应用与发展-安科瑞黄安南

摘要&#xff1a;随着我国社会经济的快速发展&#xff0c;我国科技实力得到了非常大的提升&#xff0c;当前互联网通信技术在社会中得到了广泛的应用。随着电力通信技术的快速发展与更新&#xff0c;泛在电力物联网建设成为电力通讯发展的重要方向。本文已泛在电力物联网系统为…

无中微子双贝塔衰变

无中微子双贝塔衰变 无中微子双贝塔衰变的原子核理论 双贝塔衰变的研究缘起 玛丽亚格佩特-梅耶&#xff08;Maria Goeppert-Mayer&#xff09;在1935年提出了双贝塔衰变的可能性埃托雷马约拉纳&#xff08;Ettore Majorana&#xff09;在1937年证明了如果中微子是否是Majorana…

PCL 透视投影变换(OpenGL)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 在现实生活中,我们总会注意到离我们越远的东西看起来更小。这个神奇的效果被称之为透视(Perspective)。透视的效果在我们看一条无限长的高速公路或铁路时尤其明显,正如下面图片显示的这样: 由于透视的原因,平行线…

CVE-2023-46227 Apache inlong JDBC URL反序列化漏洞

项目介绍 Apache InLong&#xff08;应龙&#xff09;是一站式、全场景的海量数据集成框架&#xff0c;同时支持数据接入、数据同步和数据订阅&#xff0c;提供自动、安全、可靠和高性能的数据传输能力&#xff0c;方便业务构建基于流式的数据分析、建模和应用。 项目地址 h…

以太网链路聚合与交换机堆叠,集群

目录 以太网链路聚合 一.链路聚合的基本概念 二.链路聚合的配置 1.手工模式 2.LACP模式 系统优先级 接口优先级 最大活动接口数 活动链路选举 负载分担 负载分担模式 三.典型使用场景 交换机之间 交换机和服务器之间 交换机和堆叠系统 防火墙双机热备心跳线 四…