【二叉树 OJ题】二叉树基础知识 与 OJ题完成(二叉树构建与遍历问题,子树查找问题)

news2024/11/25 22:48:10

二叉树 !

二叉树概念与OJ题完成

  • 二叉树 !
    • 1 树
      • 1.1 树的概念
      • 1.2 树的相关概念
      • 1.3 树的表示方式
    • 2 二叉树
      • 2.1 二叉树的概念
      • 2.2 二叉树的构建
      • 2.3 特殊的二叉树
    • 3 二叉树OJ题的解决
      • 3.1 二叉树构建与遍历问题
        • 3.1.1 二叉树遍历
        • 3.1.2 二叉树构建
        • 3.1.3 题目完成
      • 3.2 子树查找问题
  • Thanks♪(・ω・)ノ
    • 下一篇文章见!!!

1 树

1.1 树的概念

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。
在这里插入图片描述

把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。有一个特殊的结点,称为根结点,根节点没有前驱结点除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继因此,树是递归定义的

1.2 树的相关概念

1.节点的度:一个节点含有的子树的个数称为该节点的度;
2.叶节点或终端节点:度为0的节点称为叶节点;
3.非终端节点或分支节点:度不为0的节点;
4.双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
5.孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
6.兄弟节点:具有相同父节点的节点互称为兄弟节点;
7.树的度:一棵树中,最大的节点的度称为树的度;
8.节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
9.树的高度或深度:树中节点的最大层次; 如上图:树的高度为5
10.堂兄弟节点:双亲在同一层的节点互为堂兄弟;
11.节点的祖先:从根到该节点所经分支上的所有节点;
12.子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
13.森林:由m(m>0)棵互不相交的树的集合称为森林;

1.3 树的表示方式

一般来说最简单的想法是使用复杂链表结构

typedef int TreeData;
typedef struct TreeNode
{
   TreeData val;
   struct TreeNode* node1
   struct TreeNode* node2
   struct TreeNode* node3
  ...
  ...
  ...

}treenode;

可以发现,这样设置无法应对所有结构,并且冗杂混乱。所以有位大佬发明了一种十分巧妙的办法:孩子兄弟表示法
每个节点只有两个指向,其一指向最左边的孩子节点,另一指向右边的兄弟节点。如此往复成功构建了树的结构。

typedef int TreeData;
typedef struct TreeNode
{
 TreeData val; // 结点中的数据域
 struct Node* firstChild1; // 第一个孩子结点
 struct Node* pNextBrother; // 指向其下一个兄弟结点
}treenode;

在这里插入图片描述

2 二叉树

2.1 二叉树的概念

一棵二叉树是结点的一个有限集合,该集合:

  1. 或者为空
  2. 由一个根节点加上两棵别称为左子树和右子树的二叉树组成
    在这里插入图片描述
    注意:
    二叉树不存在度大于2的结点
    二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树
    现实中的二叉树

2.2 二叉树的构建

相比一般的树来说,二叉树的构建就十分简单了,只需要左右两个节点即可。

typedef char BTDataType;
typedef struct BinaryTreeNode
{
   BTDataType data;
   struct BinaryTreeNode* left;
   struct BinaryTreeNode* right;
}BTNode;

多个节点串联即可构成一棵二叉树。

2.3 特殊的二叉树

  1. 满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是
    说,如果一个二叉树的层数为K,且结点总数是 ,则它就是满二叉树。
  2. 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

在这里插入图片描述

3 二叉树OJ题的解决

3.1 二叉树构建与遍历问题

二叉树构建与遍历问题链接
在这里插入图片描述
该OJ题存在两个子问题,分别是二叉树构建和二叉树遍历。

3.1.1 二叉树遍历

我们首先解决遍历问题,遍历是构建的基础。
首先,二叉树的遍历主要有三种:

  1. 前序遍历: 先打印父节点 ,然后打印左子树,最后打印右子树。
  2. 中序遍历:先打印左子树,然后打印父节点,最后打印右子树。
  3. 后序遍历:先打印左子树,在打印右子树,最后打印父节点。
    假如有这样一棵树(题目所给)
    在这里插入图片描述

我们分别用前序遍历,中序遍历,后序遍历演示一遍。是这样的,然后我以前序遍历为例剖析一下结构。
在这里插入图片描述

前序解剖为
在这里插入图片描述
一层套一层,层层递归。
代码实现也非常简单

typedef char BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;
void BinaryTreePrevOrder(BTNode* root){
	if(!root) {
		printf("# ");
		return;
	}
	
    printf("%c ",root->data);//打印父节点
    BinaryTreePrevOrder(BTNode* root->left);//遍历左子树
    BinaryTreePrevOrder(BTNode* root->right);//遍历右子树
}

中序遍历和后序遍历只需要调换最后三行代码相对位置即可。

3.1.2 二叉树构建

题目给我们的输入样式为
输入:abc##de#g##f###(前序遍历)
‘#’表示空格,可以理解为二叉树里的空节点NULL。
‘字母’表示每个节点储存的数据
我们只要层层遍历,遇到‘#’记作NULL,反之记录节点数据,并依次遍历左子树,右子树。我们使用‘pi’为下标来完成数组的读取操作。

typedef char BTDataType;
typedef struct BinaryTreeNode
{
   BTDataType data;
   struct BinaryTreeNode* left;
   struct BinaryTreeNode* right;
}BTNode;

TreeNode* treecreate(char* str,int* pi){
       if(str[*pi] == '#'||str[*pi]=='\0') {
           (*pi)++;
           return NULL;
       }//'#'和‘\0’记作NULL
       //不为空则创建新节点
       TreeNode* node =(TreeNode*)malloc(sizeof(TreeNode));
       node->data=str[*pi];
       (*pi)++;//数组下标增加
       //遍历左子树
       node->left = treecreate(str, pi);
       //遍历右子树
       node->right = treecreate(str, pi);
       //返回当前节点
       return node;
}

int main() {  
   char str[100] = "\0";
   scanf("%s",str);
   int pi = 0;//记录下标
   //二叉树创建
   TreeNode* root = treecreate(str,&pi);
   return 0;
}

3.1.3 题目完成

根据上面两个子问题我们就解决了该OJ题
在这里插入图片描述

3.2 子树查找问题

子树查找问题链接
在这里插入图片描述
这道题我一开始的想法是检查对应每一个节点,每次只能取出一棵树中的一个节点的数据,再取出另一棵树的节点数据进行比较。但是后来发现,这种思路是非常麻烦、非常不可行的思路。

首先我完成基本的检查工作:

  1. 都为空则相同
  2. 其一为空则不同
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
    if(!root&&!subRoot) return true;//如果都为空,则相同
    if(!root) return false;//在第一条前提下 root为空肯定是假
    if(!subRoot) return false;//在第一条前提下 subRoot为空也肯定是假
}

这三条可以完成一个基本的判定。
然后我们看看如何检查子树是否存在。这个思路也很清晰:
3. 都为空则相同
4. 其一为空 则不同
5. 数据不同 则不同
6. 递归检查左右子树,必须都为真才可以

bool issame(struct TreeNode* root, struct TreeNode* subRoot){
    if(!root&&!subRoot) return true;
    if(!root) return false;
    if(!subRoot) return false;
    if(root->val != subRoot->val) return false;
   
    return issame(root->left,subRoot->left) && issame(root->right,subRoot->right);
    
}

最后关键一步是这一行代码

return issame(root,subRoot) || isSubtree(root->left,subRoot) ||isSubtree(root->right,subRoot);
  1. 如果issame检查返回真,则存在。
  2. 如果左右子树的isSubtree返回真,则存在
    主要还是issame函数的作用,后面两个isSubroot是为了防止root为空了无法正确判断来补充。
    完整代码
bool issame(struct TreeNode* root, struct TreeNode* subRoot){
    if(!root&&!subRoot) return true;
    if(!root) return false;
    if(!subRoot) return false;
    if(root->val != subRoot->val) return false;
   
    return issame(root->left,subRoot->left) && issame(root->right,subRoot->right);
    
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
    if(!root&&!subRoot) return true;
    if(!root) return false;
    if(!subRoot) return false;
        
    return issame(root,subRoot) || isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
   
    
}

Thanks♪(・ω・)ノ

下一篇文章见!!!

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

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

相关文章

Linux5.2、进程等待

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 进程等待的必要性 进程等待的方法 获取子进程status 进程等待的必要性 首先&#xff0c;子进程退出&#xff0c;如果父进程不去回收子进程资源&#xff0c;读取子进程的PCB&#xff0c;那么就会使子进程变成僵尸进程…

羊大师之冷天喝羊的好处大揭秘!

最近&#xff0c;冷天喝羊已经成为了一种趋势&#xff0c;受到了越来越多人的关注与喜爱。你可能会好奇&#xff0c;为什么冷天喝羊有那么多的好处呢&#xff1f;今天小编羊大师将带大家一起探索这个问题&#xff0c;揭秘冷天喝羊带来的种种益处。 冷天喝羊对于保持身体温暖是…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)控件的部分公共属性和事件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;控件的部分公共属性和事件 一、操作环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、公共属性 常用的公共属性有&#xff1a; 宽(with)、高(height)、…

天猫数据平台-淘宝天猫数据-天猫销售数据分析:11月天猫平台滑雪运动装备行业销量翻倍!

随着天气变冷、冬季来临&#xff0c;迎来了疫情后的首个滑雪季&#xff0c;加之自冬奥会结束以来&#xff0c;大众参与冰雪运动的热度持续攀升&#xff0c;因此&#xff0c;冰雪运动的需求正集中释放。 根据相关数据显示&#xff0c;11月以来&#xff0c;全国滑雪场门票预订量较…

智能物流解决方案:科聪料箱移动机器人助力高效运输

料箱机器人是一种智能化物流搬运设备&#xff0c;无需借助任何轨道&#xff0c;即可实现多个料箱的智能拣选、存取、搬运。以料箱为存储单元的存储形式&#xff0c;通过信息化系统的统一调度和管理&#xff0c;实现小批量、多批次、高周转率的出入库、拣选等。 ▲料箱机器人现场…

推荐一款图集打包工具,png图片打包plist工具,手把手教你使用pngPackerGUI_V2.0

png图片打包plist工具&#xff0c;手把手教你使用pngPackerGUI_V2.0此软件是在pngpacker_V1.1软件基础之后&#xff0c;开发的界面化操作软件&#xff0c;方便不太懂命令行的小白快捷上手使用。1.下载并解压缩软件&#xff0c;得到如下目录&#xff0c;双击打开 pngPackerGUI.e…

antd-table:通过rowClassName实现斑马条纹样式+通过rowSelection实现单选功能效果——基础积累

斑马条纹 对于element-ui是有个stripe斑马条纹的属性的&#xff0c;最终呈现的效果如下&#xff1a; antd-table中是没有这个属性的&#xff0c;但是可以通过rowClassName&#xff1a;可以给对应行添加指定类名。 实现方法&#xff1a; <a-table:rowClassName"getRo…

【ESXi】ESXi 版本回退

目录 8. ESXi 版本回退8.1 版本回退条件与注意事项8.2 版本回退步骤8.3 示例演示&#xff08;1&#xff09;准备工作&#xff08;2&#xff09;进入DCUI界面&#xff08;3&#xff09;按 F11 重启系统引导&#xff08;4&#xff09;进入引导选项&#xff08;5&#xff09;进入 …

【玩转Node.JS】=> 之 Buffer(缓冲器)

Node.js 是一个开源、跨平台的 JavaScript 运行时环境 文章目录 Buffer 概念Buffer 的特点创建 BufferBuffer 与字符串的转化 Buffer 的读写 Buffer 概念 Buffer 是一个类似于数组的 对象 &#xff0c;用于表示固定长度的字节序列Buffer 本质是一段内存空间&#xff0c;专门用…

android工程目录结构

App工程分为两个层次&#xff0c;一个层次是项目&#xff0c;另一个层次是模块 模块依附于项目&#xff0c;每个项目至少有一个模块&#xff0c;也能拥有多个模块 一般所言的“编译运行App”&#xff0c;指的是运行某个模块&#xff0c;而非运行某个项目&#xff0c;因为模块才…

【docker】修改docker的数据目录

背景 主节点是分配了较少内存和存储的低配机器&#xff0c;因为我们系统的rancher是用docker镜像启动的&#xff0c;而rancher和docker的默认目录都放在/var/lib下面&#xff0c;而这个/var目录目前只分配10G的存储&#xff0c;导致节点存储报警。因此想修改docker的数据目录&…

关于pycharm无法进入base界面的问题

问题&#xff1a;terminal输入activate无法进入base 解决方案 1.Cortana这边找到Anaconda Prompt右击进入文件所在位置 2. 右击进入属性 3. 复制cmd.exe开始到最后的路径 cmd.exe "/K" C:\ProgramData\anaconda3\Scripts\activate.bat C:\ProgramData\anaconda3 …

工业数据的特殊性和安全防护体系探索思考

随着工业互联网的发展&#xff0c;工业企业在生产运营管理过程中会产生各式各样数据&#xff0c;主要有研发设计数据、用户数据、生产运营数据、物流供应链数据等等&#xff0c;这样就形成了工业大数据&#xff0c;这些数据需要依赖企业的网络环境和应用系统进行内外部流通才能…

STM32——时钟树与滴答计时器

STM32——时钟树与滴答计时器 使用的开发板为stm32F407VET6的芯片,主要介绍stm32的时钟树与滴答计时器的一些理论和一个自己编写的delay函数。 时钟树的结构图可以在STM32F4xx中文参考手册.pdf中的时钟这块找到。而滴答计时器是内核资源&#xff0c;需要到Cortex M3与M4权威指南…

Vue中的数据变化监控与响应——深入理解Watchers

目录 ​编辑 前言 1. 基本用法&#xff1a; 2. 深度监听&#xff1a; 3. 立即执行&#xff1a; 4. 监听多个数据&#xff1a; 5. 清理监听器&#xff1a; 6. 监听路由变化&#xff1a; 总结&#xff1a; 我的其他博客 前言 在Vue.js中&#xff0c;watch是一种用于监听…

【MATLAB】数据拟合第11期-基于粒子群迭代的拟合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 基于粒子群迭代的拟合算法是一种优化技术&#xff0c;它基于粒子群优化算法&#xff08;PSO&#xff09;的基本思想。该算法通过群体中个体之间的协作和信息共享来寻找最优解。 在基于粒…

vue3 插槽slot

插槽是子组件中的提供给父组件使用的一个占位符&#xff0c;用 <slot> 表示&#xff0c;父组件可以在这个占位符中填充任何模板代码&#xff0c;如 HTML、组件等&#xff0c;填充的内容会替换子组件的<slot> 元素。<slot> 元素是一个插槽出口 (slot outlet)&…

自由编程学习资源:free-programming-books

最近&#xff0c;我发现了一个在GitHub上备受欢迎的项目&#xff0c;它为程序员和编程爱好者提供了丰富、免费且高质量的学习资料&#xff0c;这就是"free-programming-books"。目前&#xff0c;这个项目在GitHub上已经有305k的star&#xff0c;显示出它在开发者社区…

分享66个JavaGame源码总有一个是你想要的

分享66个JavaGame源码总有一个是你想要的 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 游戏下载链接&#xff1a;https://pan.baidu.com/s/1BUVmun2RhAY4vAMJwcY0mQ?pwd6666 提取码&#xff1a;6666 游戏项目名称 java实现…

千兆多模光模块SFP-GE-SX是什么?特点和应用领域有哪些?

千兆多模光模块SFP-GE-SX是一种用于光纤通信的光模块&#xff0c;用于传输千兆&#xff08;1 Gbps&#xff09;速率的数据。它使用多模光纤作为传输介质&#xff0c;并通过光信号来实现数据的传输。多模光纤是一种光纤&#xff0c;它具有相对较大的纤芯直径&#xff0c;通常为5…