数据结构第十四弹---链式二叉树基本操作(下)

链式二叉树

  • 1、翻转二叉树
  • 2、判断两棵树是否相同
  • 3、判断二叉树是否是单值二叉树
  • 4、对称二叉树
  • 5、判断二叉树是否是平衡二叉树
  • 6、判断二叉树是否是另一棵二叉树的子树
  • 7、二叉树的销毁
  • 8、二叉树的深度遍历
    • 8.1、前序遍历
    • 8.2、中序遍历
    • 8.3、后序遍历
  • 9、二叉树的构造和遍历
  • 总结

1、翻转二叉树

如何翻转一颗二叉树?首先我们可以先观察一下翻转前后的变化。如下图。
在这里插入图片描述
画图分析
在这里插入图片描述
通过观察,可以发现:翻转后,根的左右子树的位置交换了;根的孩子的左右子树的位置也交换了;根的孩子的孩子的左右子树的位置也交换了…

思路:
1、翻转左子树
2、翻转右子树
3、交换左右子树位置

代码实现

//翻转二叉树
BTNode* invertTree(BTNode* root)
{
	if (root == NULL)//根为空,直接返回
		return NULL;
	BTNode* left = invertTree(root->left);//翻转左子树
	BTNode* right = invertTree(root->right);//翻转右子树
	//左右子树位置交换
	root->left = right;
	root->right = left;
	return root;
}

2、判断两棵树是否相同

在这里插入图片描述
在这里插入图片描述
根据上图可知,相等的两棵树需要根节点数值相等,左右子树数值也相等。

因此可以将问题拆分为子问题。
1、两棵树根节点都为空,则相同。
2、两棵树根节点一个为空,则不相同。
3、两棵树根节点都不为空,两棵树的根的值不相等则不相同。
4、判断左右子树是否相等。

代码实现

bool isSameTree(BTNode* p, BTNode* q)
{
	if (p == NULL&&q == NULL)//两棵树均为空,则相同
		return true;
	if (p == NULL || q == NULL)//两棵树中只有一棵树为空,则不相同
		return false;
	if (p->data != q->data)//两棵树根的值不同,则不相同
		return false;
	return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);//两棵树的左子树相同并且右子树相同,则这两棵树相同
}

3、判断二叉树是否是单值二叉树

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

思路:
1、判断根节点是否为空,为空则是单值二叉树。
2、在左子树存在的情况下,判断左孩子的值是否等于根节点的值。
3、在右子树存在的情况下,判断右孩子的是否等于根节点的值。
4、判断左子树和右子树是否为单值二叉树。

代码实现

//判断二叉树是否是单值二叉树
bool isUnivalTree(BTNode* root)
{
	if (root == NULL)//根为空,是单值二叉树
		return true;
	if (root->left && root->left->data != root->data)//左孩子存在,但左孩子的值不等于根的值
		return false;
	if (root->right && root->right->data != root->data)//右孩子存在,但右孩子的值不等于根的值
		return false;
	return isUnivalTree(root->left) && isUnivalTree(root->right);//左子树是单值二叉树并且右子树是单值二叉树
}

4、对称二叉树

在这里插入图片描述
在这里插入图片描述
如上图所示,事例一为对称二叉树,事例二不为对称二叉树。可以得知,对称二叉树左孩子等于右孩子,左子树等于右子树。

思路:
1、判断根节点是否为空,为空则为对称二叉树。
2、根节点存在,且左右子树均为空,则为对称二叉树。
3、根节点存在且左右子树其中一个为空,则不为对称二叉树。
4、根节点存在且左右子树均不为空,且左右子树值不相等,则不为对称二叉树。
5、判断左子树是否等于右子树,右子树是否等于左子树。(递归,需要传两个参数,原函数为一个参数,所以创建新的函数实现递归函数)

代码实现

bool _isSymmetric(struct TreeNode* root1,struct TreeNode* root2)
{
    //1.都为空的
     if(root1==NULL && root2 == NULL)
          return true;
    //2.其中一个子树为空
    if(root1 == NULL || root2 == NULL)
          return false;
    //3.都不为空
    if(root1->val != root2->val)
           return false;
    return _isSymmetric(root1->left,root2->right)
           && _isSymmetric(root1->right,root2->left);
} 
bool isSymmetric(struct TreeNode* root) 
{
     //根为空,则为真
     if(root==NULL)
     return true;
     //将左子树与右子树进行比较 然后递归 原函数只有一个参数,可以构建一个新函数进行比较
     return _isSymmetric(root->left,root->right);
}

5、判断二叉树是否是平衡二叉树

平衡二叉树:即每个结点的左右两个子树的高度差的绝对值不超过1。
在这里插入图片描述

思路:
1、判断根节点是否为空,为空则是平衡二叉树。
2、计算左子树的高度。
3、计算右子树的高度。
4、如果左右子树的高度差不超过1并且左右子树均为平衡二叉树则为平衡二插树。

代码实现

//判断二叉树是否是平衡二叉树
bool isBalanced(BTNode* root)
{
	if (root == NULL)//空树是平衡二叉树
		return true;

	int leftDepth = BinaryTreeMaxDepth(root->left);//求左子树的深度
	int rightDepth = BinaryTreeMaxDepth(root->right);//求右子树的深度
	//左右子树高度差的绝对值不超过1 && 其左子树是平衡二叉树 && 其右子树是平衡二叉树
	return abs(leftDepth - rightDepth) < 2 && isBalanced(root->left) && isBalanced(root->right);
}

6、判断二叉树是否是另一棵二叉树的子树

在这里插入图片描述
判断二叉树是否是另一个棵树的子树:即root中是否包含与subRoot相同结构和结点值的子树。(subRoot不为空)

思路:
1、如果根节点为空,则不是。
2、判断根节点是否与子树相等,相等则是。
3、判断左子树是否与子树相等,相等则是。
4、判断右子树是否与子树相等,相等则是。

代码实现

bool isSameTree(struct TreeNode* p, struct TreeNode* q) 
{
    //1.都为空
    if(p==NULL && q==NULL)
    return true;
    //2.一个为空
    if(p==NULL || q==NULL)
    return false;
    //3.根都不为空 且val不相等
    if(p->val!=q->val)
    return false;
    //4.根不为空 且根相等 则比较左右子树
    return isSameTree(p->left,q->left) &&
    isSameTree(p->right,q->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
    if(root == NULL)
    return false;
    
    return isSameTree(root,subRoot)//根节点与子树
           ||isSubtree(root->left,subRoot)//左子树与子树
           ||isSubtree(root->right,subRoot);//右子树与子树
}

7、二叉树的销毁

二叉树的销毁跟其他数据结构的销毁基本类似,都是通过遍历销毁。此处需要通过后序遍历进行销毁,因为只有后序遍历销毁左右子树之后还能找到根节点。

代码实现

void TreeDestroy(BTNode* root)
{
	if (root == NULL)
		return;

	TreeDestroy(root->left);//销毁左子树
	TreeDestroy(root->right);//销毁右子树
	free(root);//释放根结点
}

8、二叉树的深度遍历

此处的深度遍历跟上一弹的深度遍历不太一样,前面的是通过遍历将数值打印出来,此处是将二叉树的数值通过遍历存储到一个新的数组中。

思路:
1、通过计算二叉树的有效数据个数,确定新开辟的数组的大小。
2、通过遍历将数据存储到数组中。
3、返回数组。

8.1、前序遍历

代码实现

 int RootSize(struct TreeNode* root)
 {
     return root==NULL?0:RootSize(root->left)+RootSize(root->right)+1;
 }
 void PervOrder(struct TreeNode* root,int* a,int* pi)
 {
      if(root==NULL)
      return;
      a[(*pi)++]=root->val;
      PervOrder(root->left,a,pi);
      PervOrder(root->right,a,pi);
 }
int* preorderTraversal(struct TreeNode* root, int* returnSize) 
{
    //1.计算树的元素个数
    int sz=RootSize(root);
    //2.动态开辟一个树大小的数组
    int* a=(int*)malloc(sizeof(int)*sz);
    //3.前序遍历,将树的值赋值到数组上,但是如果对原函数进行递归遍历,
    //returnSize会多次返回,解决办法是构建新的递归函数
    int i=0;//记录数组下标和大小
    PervOrder(root,a,&i);
    *returnSize=sz;
    return a;//返回数组
}

8.2、中序遍历

代码实现

  int TreeSize(struct TreeNode* root)
 {
     return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
 }
 void InOrder(struct TreeNode* root,int* a,int* pi)
 {
     if(root==NULL)
     return;
     InOrder(root->left,a,pi);
     a[(*pi)++]=root->val;
     InOrder(root->right,a,pi);
 }
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    //计算树的大小
    int sz=TreeSize(root);
    //动态开辟内存
    int* a=(int*)malloc(sizeof(int)*sz);
    //判断是否开辟成功
    if(a==NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    int i=0;
    InOrder(root,a,&i);
    //返回数据个数
    *returnSize=sz;
    //返回数组
    return a;
}

8.3、后序遍历

在这里插入图片描述

代码实现

 int TreeSize(struct TreeNode* root)
 {
     return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
 }
 void PostOrder(struct TreeNode* root,int* a,int* pi)
 {
     if(root==NULL)
     return;
     PostOrder(root->left,a,pi);
     PostOrder(root->right,a,pi);
     a[(*pi)++]=root->val;
 }
int* postorderTraversal(struct TreeNode* root, int* returnSize) 
{
    int sz=TreeSize(root);
    int* a=(int*)malloc(sizeof(int)*sz);
    if(a==NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    int i=0;
    PostOrder(root,a,&i);
    *returnSize=sz;
    
    return a;
}

9、二叉树的构造和遍历

在这里插入图片描述
思路:
1、遍历字符串,如果该字符不等于’#’,则按照先序遍历构造二叉树,然后递归构造左右子树。
2、如果字符为’#’,则不再进行构造。
3、构造完之后通过中序遍历打印数据。
代码实现

#include <stdio.h>
#include <stdlib.h>

typedef struct TreeNode
{
    struct TreeNode* left;
    struct TreeNode* right;
    char data;
}TreeNode;
//创建树
TreeNode* CreateTree(char* str, int* pi)
{
    if(str[*pi] == '#')//
    {
        (*pi)++;
        return NULL;
    }
    //不是NULL,构建结点
    TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
    root->left = NULL;
    root->right = NULL;
    root->data = str[*pi];
    (*pi)++;
    //递归构建左子树
    root->left = CreateTree(str, pi);
    //递归构建右子树
    root->right = CreateTree(str, pi);
    return root;
}
//中序遍历
void Inorder(TreeNode* root)
{
    if(root == NULL)
        return;
    Inorder(root->left);
    printf("%c ", root->data);
    Inorder(root->right);
}
int main()
{
    char str[100];
    scanf("%s", str);
    int i = 0;
    TreeNode* root = CreateTree(str, &i);
    Inorder(root);
    return 0;
}

测试
在这里插入图片描述

总结

本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

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

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

相关文章

Mysql数据库高版本向低版本迁移方法

操作步骤 1、首先低版本Mysql创建数据库 2、使用navicat工具&#xff0c;复制高版本数据库的表 3、在低版本数据库中粘贴&#xff0c;弹出数据传输界面&#xff0c;选项去掉包含字符集、包含引擎及表类型 使用该版本实现了Mysql8.0向Mysql5.5的迁移&#xff0c;如果在Mysql8.0生…

海外融合CDN之火伞云

在当今互联网全球化的时代&#xff0c;出海业务已经成为许多企业的必然选择。在海外市场上&#xff0c;快速、稳定的内容传输对于企业的成功至关重要。然而&#xff0c;如何合理的运用多家CDN供应商的资源实现智能化的调度&#xff0c;以及如何与业务更紧密地结合起来&#xff…

华为手机备份全过程(保姆级问题解决方案)

手机备份 前言主体信息备份一、关闭windows安全中心的内存完整性二、开启 USB 调试&#xff0c;尝试使用 ADB 连接三、开始备份 微信备份QQ备份写在最后 前言 我的手机是荣耀 20&#xff0c;虽然不是华为&#xff0c;但系统还是鸿蒙的系统&#xff08;毕竟那阵荣耀还是华为的子…

P4学习(一) 环境搭建

系列文章目录 第一章 P4学习入门之虚拟机环境搭建 文章目录 系列文章目录前言一、P4是什么&#xff1f;二、搭建步骤1.下载虚拟机镜像2.虚拟机管理软件载入镜像2.1 找到你镜像的所在位置2.2 打开VMware Workstation2.3 载入镜像 3.检验环境是否配置成功 P4 的真机环境搭建 前言…

transfomer中Multi-Head Attention的源码实现

简介 Multi-Head Attention是一种注意力机制,是transfomer的核心机制. Multi-Head Attention的原理是通过将模型分为多个头&#xff0c;形成多个子空间&#xff0c;让模型关注不同方面的信息。每个头独立进行注意力运算&#xff0c;得到一个注意力权重矩阵。输出的结果再通过…

大模型背景下计算机视觉年终思考小结(一)

1. 引言 在过去的十年里&#xff0c;出现了许多涉及计算机视觉的项目&#xff0c;举例如下&#xff1a; 使用射线图像和其他医学图像领域的医学诊断应用使用卫星图像分析建筑物和土地利用率相关应用各种环境下的目标检测和跟踪&#xff0c;如交通流统计、自然环境垃圾检测估计…

国内首款支持苹果Find My芯片-伦茨科技ST17H6x

深圳市伦茨科技有限公司&#xff08;以下简称“伦茨科技”&#xff09;发布ST17H6x Soc平台。成为继Nordic之后全球第二家取得Apple Find My「查找」认证的芯片厂家&#xff0c;该平台提供可通过Apple Find My认证的Apple查找&#xff08;Find My&#xff09;功能集成解决方案。…

PYTHON通过跳板机巡检CENTOS的简单实现

实现的细节和引用的文件和以前博客记录的基本一致 https://shaka.blog.csdn.net/article/details/106927633 差别在于,这次是通过跳板机登陆获取的主机信息,只记录差异的部份 1.需要在跳板机相应的路径放置PYTHON的脚本resc.py resc.py这个脚本中有引用的文件(pm.sh,diskpn…

代码随想录 Leetcode242. 有效的字母异位词

题目&#xff1a; 代码&#xff08;首刷看解析 2024年1月14日&#xff09;&#xff1a; class Solution { public:bool isAnagram(string s, string t) {int hash[26] {0};for(int i 0; i < s.size(); i) {hash[s[i] - a];}for(int i 0; i < t.size(); i) {hash[t[i]…

java编程解小学生一年级竞赛题

抖音教学视频 目录 1、题目三角形加起来为10 大纲 1、题目三角形加起来为10 连接&#xff1a;小学一年级数学竞赛练习题3套&#xff0c;有点难度&#xff01; 第16题 此方法不是最优解&#xff0c;穷举法&#xff0c;比较暴力解决 主要给大家演示如何用编程去解决我们的实…

智能寻迹避障清障机器人设计(电路图附件+代码)

附 录 智能小车原理图 智能小车拓展板原理图 智能小车拓展板PCB 智能小车底板PCB Arduino UNO原理图 Arduino UNO PCB 程序部分 void Robot_Traction() //机器人循迹子程序{//有信号为LOW 没有信号为HIGHSR digitalRead(SensorRight);//有信号表明在白…

vue3 - 自定义弹框组件

写了一个弹框组件 <template><transition name"modal-fade"><div v-if"showFlag" class"myModal"><div class"content"><div class"topBox"><div class"leftTitle"><spa…

Chapter 8 怎样使用类和对象(下篇)

⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️⚡️ 8.2 对象数组 1.对象数组的每一个元素都是同类的对象 2.在建立数组时&#xff0c;同样…

day18【LeetCode力扣】19.删除链表的倒数第N个结点

day18【LeetCode力扣】19.删除链表的倒数第N个结点 1.题目描述 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&a…

SpringBoot+SSM项目实战 苍穹外卖(10) Spring Task WebSocket

继续上一节的内容&#xff0c;本节学习Spring Task和WebSocket&#xff0c;并完成订单状态定时处理、来单提醒和客户催单功能。 目录 Spring Task&#xff08;cron表达式&#xff09;入门案例 订单状态定时处理WebSocket入门案例 来单提醒客户催单 Spring Task&#xff08;cron…

pyqt调用UI和开启子进程

UI制作 qrc 注意调用UI前把样式表里绑定的资源(qrc)转换成py导入进去 xxx.qrc转xxx.py 两种方法 1命令 pyrcc5 -o icons_rc.py icons.qrc 2外部工具pyrcc 实参 -o $FileNameWithoutExtension$.py $FileNameWithoutExtension$.qrcsdz.qrc→→sdaz.py 在代码里写 import…

Springboot3新特性:开发第一个 GraalVM 本机应用程序(完整教程)

在讲述之前&#xff0c;各位先自行在网上下载并安装Visual Studio 2022&#xff0c;安装的时候别忘了勾选msvc 概述&#xff1a;GraalVM 本机应用程序&#xff08;Native Image&#xff09;是使用 GraalVM 的一个特性&#xff0c;允许将 Java 应用程序编译成本机二进制文件&am…

视频剪辑软件Camtasia2024最新版本快捷键大全

Camtasia Studio是一款专门录制屏幕动作的工具&#xff0c;它能在任何颜色模式下轻松地记录 屏幕动作&#xff0c;包括影像、音效、鼠标移动轨迹、解说声音等等。 今天来给大家介绍一下Camtasia快捷键的相关内容&#xff0c;Camtasia也是一个十分好用的电脑屏幕录制与视频剪辑…

GRE隧道(初级VPN)配置步骤

一、拓朴图&#xff1a; 二、配置步骤&#xff1a; 1、配置IP 2、R1、R2 配置nat&#xff0c;代理内网地址通过G0/0/0口上外网 acl 2000rule permit source anyquit # int G0/0/0ip addr 100.1.1.1 24nat outbound 2000 # 3、R1、R2 配置默认出口路由G0/0/0&#xff0c;这一…

Windows启动MongoDB服务报错(错误 1053:服务没有及时响应启动或控制请求)

问题描述&#xff1a;修改MongoDB服务bin目录下的mongod.cfg&#xff0c;然后在任务管理器找到MongoDB服务-->右键-->点击【开始】&#xff0c;启动失败无提示&#xff1a; 右键点击任务管理器的MongoDB服务-->点击【打开服务】&#xff0c;跳转到服务页面-->找到M…