二叉树的前序遍历 、二叉树的最大深度、平衡二叉树、二叉树遍历(leetcode)

目录

一、二叉树的前序遍历 

方法一:全局变量记录节点个数

方法二:传址调用记录节点个数

二、二叉树的最大深度

三、平衡二叉树

四、二叉树遍历


一、二叉树的前序遍历 

 

方法一:全局变量记录节点个数

计算树的节点数:
函数TreeSize用于递归地计算二叉树中的节点数。如果树为空(即根节点为NULL),则返回0。否则,返回左子树的节点数、右子树的节点数和1(表示当前节点)的总和。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;          // 节点的值  *  struct TreeNode *left;  // 指向左子节点的指针  *  struct TreeNode *right; // 指向右子节点的指针* };*/
/*** Note: The returned array must be malloced, assume caller calls free().*/
//先求树有几个节点
int TreeSize(struct TreeNode* root)
{// 如果树为空(即根节点为NULL),则返回0  // 否则,返回左子树节点数 + 右子树节点数 + 1(当前节点)return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

_prevOrder函数:
这是一个辅助函数,用于递归地执行前序遍历。它首先将当前节点的值存储在数组a中,然后递归地遍历左子树和右子树。注意,这里直接使用了全局变量i来更新数组索引。

定义一个全局变量i

// 前序遍历二叉树的辅助函数  
void _prevOrder(struct TreeNode* root, int* a) {  // 如果当前节点为空,则直接返回  if (root == NULL) {  return;  }  // 将当前节点的值存储到数组中,并使用全局变量i作为索引  a[i] = root->val;  // 递增全局变量i  ++i;  // 递归遍历左子树  _prevOrder(root->left, a);  // 递归遍历右子树  _prevOrder(root->right, a);  
}

preorderTraversal函数:
这是主函数,用于执行前序遍历并返回结果数组。它首先使用TreeSize函数计算树的节点数,然后动态分配一个足够大的整数数组来存储结果。接下来,它调用_prevOrder函数来执行前序遍历,并填充数组。最后,它设置returnSize为树的节点数,并返回结果数组。

// 执行前序遍历并返回结果数组的主函数  
int* preorderTraversal(struct TreeNode* root, int* returnSize) {  //每次调用函数时,都要把i初始化//如果没有初始化,则i会一直叠加,无法重复使用i = 0;  // 调用TreeSize函数计算二叉树的节点数  int size = TreeSize(root);  // 动态分配结果数组,大小为节点数  int* a = (int*)malloc(size * sizeof(int));  // 调用辅助函数_prevOrder执行前序遍历,填充数组a  _prevOrder(root, a);  // 设置返回数组的大小为树的节点数,通过指针参数returnSize返回  *returnSize = size;        // 返回结果数组a的指针  return a;                  
}

方法二:传址调用记录节点个数

前面与方法一相同,不再过多赘述

_prevOrder 函数:
辅助函数,用于递归地执行前序遍历。它接受三个参数:当前节点 root、用于存储遍历结果的数组 a 和一个指向整数的指针 pi(表示当前数组索引)。函数首先将当前节点的值存储在数组 a 的相应位置,然后递增索引 pi。接下来,它递归地遍历左子树和右子树。

// 前序遍历二叉树的辅助函数  
void _prevOrder(struct TreeNode* root, int* a, int* pi) {  // 如果当前节点为空,则直接返回  if (root == NULL) {  return;  }  // 将当前节点的值存储到数组中,并递增索引pi  a[*pi] = root->val;  ++(*pi);  // 递归遍历左子树  _prevOrder(root->left, a, pi);  // 递归遍历右子树  _prevOrder(root->right, a, pi);  
}

preorderTraversal 函数:
这是主函数,用于执行前序遍历并返回结果数组。它首先调用 TreeSize 函数(虽然这里没有给出 TreeSize 的实现,但我们可以假设它的功能是计算树的节点数)来计算树的节点数,然后动态分配一个足够大的整数数组来存储结果。接着,它调用 _prevOrder 函数来执行前序遍历,并填充数组。最后,它设置 returnSize 为树的节点数,并返回结果数组。

int* preorderTraversal(struct TreeNode* root, int* returnSize) {  int i = 0; // 初始化索引为0  int size = TreeSize(root); // 假设TreeSize函数能正确计算节点数  int* a = (int*)malloc(size * sizeof(int)); // 动态分配数组  _prevOrder(root, a, &i); // 执行前序遍历,填充数组  *returnSize = size; // 设置返回数组的大小  return a; // 返回结果数组  
}

二、二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。

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

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/
int maxDepth(struct TreeNode* root) {  // 如果根节点为空,说明树是空的,因此深度为0。  if (root == NULL)  return 0;  // 递归地计算左子树的最大深度。  int leftDepth = maxDepth(root->left);  // 递归地计算右子树的最大深度。  int rightDepth = maxDepth(root->right);  // 返回左、右子树中深度较大的一个,并加上当前节点的高度1。  return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;  
}

三、平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/int maxDepth(struct TreeNode* root) {  // 如果根节点为空,说明树是空的,因此深度为0。  if (root == NULL)  return 0;  // 递归计算左子树的最大深度。  int leftDepth = maxDepth(root->left);  // 递归计算右子树的最大深度。  int rightDepth = maxDepth(root->right);  // 返回左、右子树中较大的深度值加1(加上当前节点的高度)。  return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;  
}
bool isBalanced(struct TreeNode* root) {  // 如果根节点为空,那么这棵空树被认为是平衡的。  if (root == NULL)  return true;  // 计算左子树的最大深度。  int leftDepth = maxDepth(root->left);  // 计算右子树的最大深度。  int rightDepth = maxDepth(root->right);  // 判断当前节点的左右子树深度差是否小于等于1,并且左右子树本身也都是平衡的。   return abs(leftDepth - rightDepth) <= 1  && isBalanced(root->left)  // 递归检查左子树是否平衡。  && isBalanced(root->right); // 递归检查右子树是否平衡。  
}

四、二叉树遍历

编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。 

#include <stdio.h>  
#include <stdlib.h> // 需要包含stdlib.h来使用malloc和exit函数  // 定义二叉树节点的结构体  
typedef struct TreeNode  
{  struct TreeNode* left;  // 左子树指针  struct TreeNode* right; // 右子树指针  char val;               // 节点值  
} TNode;  // 创建一个二叉树的函数,a是包含节点值的字符串,pi是指向当前要处理的字符的索引的指针  
TNode* CreatTree(char* a, int* pi)  
{  // 如果当前字符是'#',表示这是一个空节点  if (a[*pi] == '#')  {  ++(*pi); // 增加索引  return NULL; // 返回空指针表示这是一个空节点  }  // 为新节点分配内存  TNode* root = (TNode*)malloc(sizeof(TNode));  if (root == NULL)  {  printf("malloc fail\n"); // 如果分配失败,输出错误信息  exit(-1); // 退出程序  }  // 设置节点的值,并增加索引  root->val = a[*pi];  ++(*pi);  // 递归地创建左子树和右子树  root->left = CreatTree(a, pi);  root->right = CreatTree(a, pi);  return root; // 返回新创建的节点  
}  
// 中序遍历二叉树的函数  
void InOrder(TNode* root) // 注意:函数名应该是InOrder,而不是InOeder(这里有一个拼写错误)  
{  if (root == NULL) // 如果节点为空,直接返回  return;  InOrder(root->left);  // 遍历左子树  printf("%c ", root->val); // 输出节点的值  InOrder(root->right); // 遍历右子树  
}  int main() {  char str[100]; // 存储节点值的字符串  scanf("%s", str); // 读取输入字符串,注意应该直接传入数组名int i = 0; // 索引初始化为0  TNode* root = CreatTree(str, &i); // 创建二叉树,并将根节点赋值给root  InOrder(root); // 中序遍历二叉树并输出结果  return 0; 
}

祝大家新年快乐!!!

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。

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

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

相关文章

java基础-回忆性记录3

运算符 算数运算符 运算符对常量或者变量进行操作的符号。 运算符吧常量或者变量连接起来符合java语法的式子可以称为表达式。 不同运算符连接表达式体现是不同类型。 符号作用说明加-减*乘/除%取余获取的是两个数据做除法的余数 注意&#xff1a; /和%的区别&#xff1a…

机器视觉在医学影像与医疗领域的应用及前景

引言 随着人工智能技术的飞速发展&#xff0c;机器视觉在医学影像和医疗领域中扮演着越来越重要的角色。机器视觉技术如何在医院领域提高诊断准确性、加快治疗流程以及改善患者体验。本文将探讨机器视觉算法的重要性、使用场景&#xff0c;并对其在医院领域应用的前景提出个人见…

Linux mdu命令教程:如何有效地使用mdu命令(附实例教程和注意事项)

Linux mdu命令介绍 mdu命令是Linux系统中的一个命令&#xff0c;全称为My Disk Usage&#xff0c;它用于显示目录或文件所占用的磁盘空间。 Linux mdu命令适用的Linux版本 mdu命令在大多数Linux发行版中都可以使用&#xff0c;包括但不限于Ubuntu, Debian, Fedora, CentOS等…

【PHP】获取 URL 中域名后的路径

目录 1.指定的url 2.当前请求的url 1.指定的url 如果您想从指定的 URL 中获取域名后的路径&#xff0c;可以使用 PHP 的 parse_url() 函数。以下是一个示例&#xff0c;展示了如何从指定的 URL 中获取域名后的路径&#xff1a; <?php$url https://example.com/path/to/r…

第83讲:MySQL数据库备份工具及备份策略的核心概念

文章目录 1. MySQL数据库库数据备份的理念2.MySQL数据库备份工具介绍3.逻辑备份与物理备份的比较4.数据库的备份策略 1. MySQL数据库库数据备份的理念 数据备份是作为运维来说必不可少的一个环节&#xff0c;无论是数据库数据、程序中间件都需要定期备份。 在进行备份之前首先…

计算机毕业设计-----SSM场地预订管理系统

项目介绍 本项目分为前后台&#xff0c;前台为普通用户登录&#xff0c;后台为管理员登录&#xff1b; 用户角色包含以下功能&#xff1a; 按分类查看场地,用户登录,查看网站公告,按分类查看器材,查看商品详情,加入购物车,提交订单,查看订单,修改个人信息等功能。 管理员角…

分布式【Zookeeper】

1.1 ZooKeeper 是什么 ZooKeeper 是 Apache 的顶级项目。ZooKeeper 为分布式应用提供了高效且可靠的分布式协调服务&#xff0c;提供了诸如统一命名服务、配置管理和分布式锁等分布式的基础服务。在解决分布式数据一致性方面&#xff0c;ZooKeeper 并没有直接采用 Paxos 算法&…

爬虫工作量由小到大的思维转变---<第三十四章 Scrapy 的部署scrapyd+Gerapy>

前言: scrapy-redis没被部署,感觉讲起来很无力;因为实在编不出一个能让scrapy-redis发挥用武之地的案子;所以,索性直接先把分布式爬虫的部署问题给讲清楚!! 然后,曲线救国式地再在部署的服务器上,讲scrapy redis我感觉这样才好! 正文: 现在还有不少人在用scrapy web进行爬虫管…

【深入探索Python库】操作系统功能的接口OS库(2)

系列文章目录 深入探索Python库之操作系统功能的接口OS库&#xff08;1&#xff09; 深入探索Python库之操作系统功能的接口OS库&#xff08;2&#xff09; 文章目录 系列文章目录引言系统信息进程管理结论 引言 前篇文章介绍了python库中os库的核心用途&#xff0c;包括文件…

2024,启动(回顾我的2023)

零.前言 打开博客想写个年度总结&#xff0c;发现已经半年没有更新文章了&#xff0c;排名从几千掉到了几万&#xff0c;不过数据量还是不错的。 时间过得可真快&#xff0c;2023年是充满动荡的一年&#xff0c;上半年gpt横空出世&#xff0c;下半年各种翻车暴雷吃瓜吃到嘴软…

系统编程--VIM

这里写目录标题 vim三种工作模式进入文本模式的快捷键在命令模式下进行文本编辑 一级目录二级目录二级目录二级目录 一级目录二级目录二级目录二级目录 一级目录二级目录二级目录二级目录 一级目录二级目录二级目录二级目录 vim 三种工作模式 具体可见第二章对vim的详细介绍 …

前端vue部署nginx多端口文件配置

nginx.conf 文件 worker_processes 1;events {worker_connections 1024; }http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 开启gzip压缩gzip on;gzip_static on;# 不压缩临界值&#xff0c;大于1K的才…

C:宏:编程风格:井号与define之间的空格

在这一篇中有提到&#xff0c;井号与define之间空格&#xff0c;可能导致搜索上的一些问题。 https://mzhan017.blog.csdn.net/article/details/135289451 今天看到有专门做这个空格的修改&#xff1a; https://sourceware.org/git/?pglibc.git;acommitdiff;hfcf70d4114db9ff…

第二节 linux操作系统安装与配置

一&#xff1a;Vmware虚拟机安装与使用   ①VMware是一个虚拟PC的软件&#xff0c;可以在现有的操作系统上虚拟出一个新的硬件环境&#xff0c;相当于模拟出一台新的PC &#xff0c;以此来实现在一台机器上真正同时运行多个独立的操作系统。   ②VMware主要特点&#xff1a…

ES6 Module详解

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

SELinux 基本原理

本文讲述 SELinux 保护安全的基本原理 首发公号&#xff1a;Rand_cs 安全检查顺序 不废话&#xff0c;直接先来看张图 当我们执行系统调用的时候&#xff0c;会首先对某些错误情况进行检查&#xff0c;如果失败通常会得到一些 error 信息&#xff0c;通过查看全局变量 errno …

Python PDF转换为图片的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Kingbase单实例场景下更新license步骤

查进程 确定在运行的kingbase服务是在用的服务&#xff0c;避免因多个kingbase服务混淆 [kingbasenode1 V8]$ ps -ef | grep Kingbase kingbase 3190 1 0 10:06 ? 00:00:00 /KingbaseES/V8/Server/bin/kingbase -D /data 查看license信息 license文件位置&…

基于Flutter构建小型新闻App

目录 1. 概述 1.1 功能概述 1.2 技术准备 1.3 源码地址 2. App首页 2.1 pubspec依赖 2.2 热门首页组件 2.2.1 DefaultTabController 2.2.2 Swiper 2.3 新闻API数据访问 2.4 热门首页效果图 3. 新闻分类 3.1 GestureDetector 3.2 新闻分类效果图 4. 收藏功能 4…

sentinel相关面试题及答案

数据结构和算法 1、什么是哨兵值&#xff1f;它在算法中是如何使用的&#xff1f; 哨兵值是在计算中用作标记或信号的特殊值&#xff0c;通常用于指示数据结构的边界或结束&#xff0c;或者作为检测特定条件的触发器。在算法中&#xff0c;哨兵值的使用可以简化代码并提高效…