二叉树的前序遍历 、二叉树的最大深度、平衡二叉树、二叉树遍历(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; 
}

祝大家新年快乐!!!

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

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

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

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

相关文章

Zookeeper注册中心实战

Java学习手册面试指南&#xff1a;https://javaxiaobear.cn Spring Cloud Zookeeper通过自动配置和绑定到 Spring 环境和其他 Spring 编程模型习惯用法&#xff0c;为 Spring Boot 应用程序提供Apache Zookeeper集成。通过一些简单的注释&#xff0c;您可以快速启用和配置应用…

51单片机中TCON, IE, PCON等寄存器的剖析

在单片机中&#xff0c;如何快速通过名字记忆IQ寄存器中每一个控制位的作用呢&#xff1f; IE&#xff08;interrupt enable&#xff09;寄存器中&#xff0c;都是中断的使能位置。 其中的EA&#xff08;enable all&#xff09;是总使能位&#xff0c;ES(enable serial)是串口…

Head First Design Patterns - 装饰者模式

什么是装饰者模式 装饰者模式动态地将额外责任附加到对象上。对于拓展功能&#xff0c;装饰者提供子类化的弹性替代方案。 --《Head First Design Patterns》中的定义 为什么会有装饰者模式 根据上述定义&#xff0c;简单来说&#xff0c;装饰者模式就是对原有的类&#xff0c…

STM32与TB6612电机驱动器的基础入门教程

TB6612是一款常用的双路直流电机驱动芯片&#xff0c;适用于小型机器人以及其他需要控制电机方向和转速的应用。在STM32微控制器的配合下&#xff0c;可以实现对TB6612电机驱动器的控制&#xff0c;进而实现电机的控制。本文将带领读者一步步了解如何搭建基于STM32与TB6612的电…

华为云默认安全组配置规则说明

华为云服务器默认安全组可选Sys-default、Sys-WebServer或Sys-FullAccess。default是默认安全组规则&#xff0c;只开放了22和3389端口&#xff1b;Sys-WebServer适用于Web网站开发场景&#xff0c;开放了80和443端口&#xff1b;Sys-FullAccess开放了全部端口。阿腾云atengyun…

机器学习——主成分分析(PCA)

目录 背景 引入 特征维度约减 特征维度约减的概念 为何要维度约减? 维度约减的应用 常规维度约减方法 主成分分析 主成分分析 (PCA)基本思路 主成分的代数定义和代数推导 主成分的代数定义 主成分的代数推导 PCA算法两种实现方法 1、基于特征值分解协方差矩阵实…

以太网二层交换机实验

实验目的&#xff1a; &#xff08;1&#xff09;理解二层交换机的原理及工作方式&#xff1b; &#xff08;2&#xff09;利用交换机组建小型交换式局域网。 实验器材&#xff1a; Cisco packet 实验内容&#xff1a; 本实验可用一台主机去ping另一台主机&#xff0c;并…

GRU算法

前置知识&#xff1a;RNN&#xff0c;LSTM LSTM需要训练的参数很多&#xff0c;极消耗计算资源。GRU是一种LSTM的改进算法&#xff0c;参数更少&#xff0c;更容易训练。 它将忘记门和输入门合并成为一个单一的更新门&#xff0c;同时合并了数据单元状态和隐藏状态&#xff0…

系列二、RestTemplate简介

一、RestTemplate简介 1.1、概述 RestTemplate是一种便捷的访问RestFul服务的模板类&#xff0c;是Spring提供的用于访问Rest服务的客户端模板工具集&#xff0c;它提供了多种便捷访问远程HTTP服务的方法。 1.2、API https://docs.spring.io/spring-framework/docs/5.2.2.REL…

Linux实战:部署基于Postfix 与 Dovecot 的邮件系统

一、电子邮件系统简介 在电子邮件系统中&#xff0c;为用户收发邮件的服务器名为邮件用户代理&#xff08;Mail User Agent&#xff0c;MUA&#xff09;&#xff0c;MTA &#xff08;邮件传输代理&#xff09;的工作职责是转发处理不同电子邮件服务供应商之间的邮件&#xff0…

docker 部署教学版本

文章目录 一、docker使用场景及常用命令1&#xff09;docker使用场景2&#xff09;rocky8(centos8)安装 docker3&#xff09;docker 常用命令补充常用命令 二、 单独部署每个镜像&#xff0c;部署spring 应用镜像推荐&#xff08;2023-12-18&#xff09;1、 安装使用 mysql1.1 …

WEB 3D技术 three.js通过光线投射 完成几何体与外界的事件交互

本文 我们来说 光线投射 光线投射技术是用于3维空间场景中的交互事件 我们先编写代码如下 import ./style.css import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";const scene new THRE…

Django Web框架

1、创建PyCharm项目 2、安装框架 pip install django 3、查看安装的包列表 4、使用命令创建django项目 django-admin startproject web 5、目录结构 6、运行 cd web python manage.py runserver7、初始化后台登录的用户名密码 执行数据库迁移生成数据表 python manage.p…

VMware17安装Centos 7.9

1.下载VMware17&#xff0c;下载 VMware Workstation Pro | CN 没有注册码&#xff0c;某多&#xff0c;某宝2元子买一个&#xff1b; 2.下载centos7.9镜像&#xff0c; 3.选择稍后安装操作系统 (如果选择安装程序光盘映像文件&#xff0c;则会按照最小系统自动安装) 4.选择…

华为鸿蒙运行Hello World

前言&#xff1a; 从11月中旬开始通过B站帝心接触鸿蒙&#xff0c;至今一个半月左右不到&#xff0c;从小白到入坑&#xff0c;再到看官网案例&#xff0c;分析案例&#xff0c;了解技术点&#xff0c;还需要理清思路&#xff0c;再写博客&#xff0c;在决定写 &#xff1c;Har…

跟着cherno手搓游戏引擎【3】事件系统和预编译头文件

不多说了直接上代码&#xff0c;课程中的架构讲的比较宽泛&#xff0c;而且有些方法写完之后并未测试。所以先把代码写完。理解其原理&#xff0c;未来使用时候会再此完善此博客。 文件架构&#xff1a; Event.h:核心基类 #pragma once #include"../Core.h" #inclu…

【java爬虫】股票数据获取工具前后端代码

前面我们有好多文章都是在介绍股票数据获取工具&#xff0c;这是一个前后端分离项目 后端技术栈&#xff1a;springboot&#xff0c;sqlite&#xff0c;jdbcTemplate&#xff0c;okhttp 前端技术栈&#xff1a;vue&#xff0c;element-plus&#xff0c;echarts&#xff0c;ax…

WPF+Halcon 培训项目实战 完结(13):HS 鼠标绘制图形

文章目录 前言相关链接项目专栏运行环境匹配图片矩形鼠标绘制Halcon添加右键事件Task封装运行结果个人引用问题原因推测 圆形鼠标绘制代码运行结果 课程完结&#xff1a; 前言 为了更好地去学习WPFHalcon&#xff0c;我决定去报个班学一下。原因无非是想换个工作。相关的教学视…

Redis 与 Spring: 解决序列化异常的探索之旅

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

数据结构【线性表篇】(五)

数据结构【线性表篇】(五&#xff09; 文章目录 数据结构【线性表篇】(五&#xff09;前言为什么突然想学算法了&#xff1f;为什么选择码蹄集作为刷题软件&#xff1f; 目录一、队列括号匹配(代码用不上&#xff0c;需改成加减乘除应用题) 二、串(一)、串的存储结构(二)、朴素…