数据结构基础8:二叉树oj+层序遍历。

二叉树oj+层序遍历

  • 题目一:二叉树的销毁:
    • 方法一:前序遍历:
    • 方法二:后序遍历:
  • 题目二:二叉树查找值为x的节点
    • 方法一:
    • 方法二:
    • 方法三:
  • 题目三:层序遍历:
    • 方法一:
  • 题目四:相同的树:
    • 方法一:
  • 题目五:对称二叉树:
    • 方法一:
  • 题目五:另一颗树的子树:
    • 方法一:
  • 题目六:二叉树的前序遍历:
    • 方法一:
    • 拓展:
  • 题目七:翻转二叉树:
    • 方法一:

题目一:二叉树的销毁:

方法一:前序遍历:

1.前序遍历需要先销毁根节点:
2.在销毁节点之前需要保存左右节点:
3.通过保存的节点的地址再一次进入函数进行递归:
4.总结:相当于从上向下遍历:

//2.销毁://方法一:(先序的销毁)保存根节点的左右节点的地址销毁自己。
void BeforeTreeDestory(struct TreeNode* root)
{//1.根节点为空:if (root == NULL)return;//2.保存左右节点的根节点:struct TreeNode* left = root->left;struct TreeNode* right = root->right;free(root);//3.进入递归:BeforeTreeDestory(left);BeforeTreeDestory(right);
}

方法二:后序遍历:

1.左子树右子树根,左子树又有左子树右子树根。
2.到走到返回的时候,这个时候左和右的走完回来了就可以销毁当前树的根
3.总结:这是一个先到最然后再去从下到上的销毁。
4.好处:不需要像前序遍历去保存左右节点的地址再一次进入递归(在返回的时候就可以销毁节点)

//方法二:(后序遍历)先进入左右子树然后这是一种从下到上的销毁:
void EndTreeDestory(struct TreeNode* root)
{if (root = NULL)return;//进入左右子树回来才销毁:EndTreeDestory(root->left);EndTreeDestory(root->right);//销毁根节点:free(root);
}

题目二:二叉树查找值为x的节点

方法一:

1.使用先序遍历;
///
2.返回的条件:
1.根为空就返回说明没有找到:
2.找到值为x的节点返回节点的地址。
3.注意:数值不相同不需要返回说明还没有找到不需要返回:


3.返回的是节点的地址如果使用&& 和 || 逻辑运算符是不会返回地址的是只会返回0,1的这是需要注意的。
4.递归注意:因为我们需要返回节点的地址是需要从return一个节点之后从递归开辟的栈帧空间中带回来:

struct TreeNode* BinaryTreeFind(struct TreeNode* root, TreeNodeData x)
{//1.根节点为空:if (root == NULL)return NULL;//2.数值相同(找到值为X的节点不需要继续往下找了)://只有数值相同的根节点才会被返回回来:if (root->val == x)return root;//3.进入左右子树,这个数值到了非常深才可以被找到:struct TreeNode* tmp1 = BinaryTreeFind(root->left, x);if (tmp1 != NULL)return tmp1;struct TreeNode* tmp2 = BinaryTreeFind(root->right, x);if (tmp2 != NULL)return tmp2;//左右子树都没有找到的情况:return NULL;}

方法二:

1.在方法一的基础上进行优化:
2.你会发现根据上面的两个判断:
1.如果根节点为空就返回NULL
2.如果数据相同就返回节点
3.如果这颗树没有数值相同的节点就返回NULL
总结:不需要对函数返回值进行判空处理直接让返回值作为判断条件是空就不会进入语句里面,如果不是空就一定是数值相等的节点的地址。返回地址就没有问题。

struct TreeNode* BinaryTreeFind(struct TreeNode* root, TreeNodeData x)
{//1.根节点为空:if (root == NULL)return NULL;//2.数值相同(找到值为X的节点不需要继续往下找了)://只有数值相同的根节点才会被返回回来:if (root->val == x)return root;//方法二:struct TreeNode* tmp = NULL;tmp = BinaryTreeFind(root->left, x);if (tmp)return tmp;tmp = BinaryTreeFind(root->right, x);if (tmp)return tmp;return NULL;
}

方法三:

1.如果左子树没有节点的话就直接返回右子树的函数返回值就可以:
2.右子树中无非只有两个情况:
1.有数据返回固定的节点地址:
2.找到底没有数据返回NULL
所以右子树的返回就不需要去判断:

struct TreeNode* BinaryTreeFind(struct TreeNode* root, TreeNodeData x)
{//1.根节点为空:if (root == NULL)return NULL;//2.数值相同(找到值为X的节点不需要继续往下找了)://只有数值相同的根节点才会被返回回来:if (root->val == x)return root;//方法三:struct TreeNode* tmp = NULL;tmp = BinaryTreeFind(root->left, x);if (tmp)return tmp;return BinaryTreeFind(root->right, x);//1.返回值需要接受,层层接受。//2.防止返回值为空。//3.或和与的运算符返回的值是0/1 地址丢失!
}

题目三:层序遍历:

方法一:

1.层序顾名思义就是一层一层的去遍历数据:
2.可以使用队列的数据结构保存数据:、
3.让根带左右子树
4.在根节点被pop之前top出节点并且访问数值去打印并且将左右子树的根节点入队列:
5.当队列为空说明二叉树的所有节点已经被层序遍历完全了:

//4.层序遍历: 队列存储:
void LevelOrder(struct TreeNode* root)
{assert(root != NULL);//初始化队列:Que pQ;QueueInit(&pQ);//入根节点:QueuePush(&pQ, root);while (!QueueEmpty(&pQ)){//获取堆头的数据QueueDatatype top = QueueFront(&pQ);//打印队头数据:if(top!=NULL)printf("%d ", top->val);//出去之前把孩子带进来(不需要递归的!!!)if(top->left!=NULL)QueuePush(&pQ, top->left);if(top->right!=NULL)QueuePush(&pQ, top->right);//pop数据:QueuePop(&pQ);}//销毁队列:QueueDestor(&pQ);}

题目四:相同的树:

请添加图片描述
相同的树:题目链接

方法一:

bool isSameTree(struct TreeNode* p, struct TreeNode* q){//1.如果两个都是空节点说明相同if(p==NULL && q==NULL)return true;//2.经过1的判断p,q中至少有一个不是空是有数值的://这样的情况如果进入一定是false。if(p==NULL || q==NULL)return false;//3.经过1,2的判断到这里一定满足两个节点都不是空节点。//两个情况://1.两个节点的值不相同返回false//2.两个节点的值相同但是还没有找完所有的节点所以继续进入递归寻找:if(p->val != q->val)return false;//4.如果两个 左子树对应已经有不相同的了就不需要进入右树了:return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}

题目五:对称二叉树:

方法一:

1.这个题目和上面那个有一点点相似,这里比较一颗树的左右子树是否对称。上一个题目是比较直接给好的两个数的是否相同:
2.我们可以写一个子函数去传这一颗树的左右子树的根节点作为新的两颗树的根节点判断是否对称:
3.判断对称是判断相反的节点值是否相同(不同于判断俩颗树的相同相对位置的值是否相同)

请添加图片描述
对称二叉树:题目链接

bool isdouSymmetric(struct TreeNode* p ,struct TreeNode* q)
{//两个都为空,走到底了!if(p==NULL && q==NULL)return true;//一个空,一个不是空:if(p==NULL || q==NULL)return false;//两个都不是空:Lif(p->val != q->val)return false;//第一个是判断左数的左和右树的右的对称://第二个是判断左数的右和右树的左的对称return isdouSymmetric(p->left , q->right)&&isdouSymmetric( p->right ,q->left );
}bool isSymmetric(struct TreeNode* root){//写一个子函数进入左右子树:return isdouSymmetric(root->left,root->right);
}

题目五:另一颗树的子树:

在这里插入图片描述
另一颗树的子树:题目链接

方法一:

1.有两个树一个树是父母。一颗树是儿子在父母中有可能找到儿子。
2.注意二子要和父母中的这个树完全相同直到后面都为空了不能说一部分相同后面还有一部分不相同的两个树:
3.我们前面写过判断两个数是否相同的函数现在找到父母这个数子树中的一个根和待比较树的根节点的相同就有可能存在相同的子树
4.当父母这个数到空就说明这颗子树没有相同的树包括没有数值的相等:
5.原函数使用 || 连接的好处是如果左树中有相同的子树并且返回了true就不需要再加入右树去判断,如果左树中没有相同的树还可以到右树中去寻找。只有左右都为false才返回false表示不存在相同的子树

bool isSameTree(struct TreeNode* p, struct TreeNode* q){//1.两个空数if(q==NULL && p==NULL){return true;}//2.一个为空 另一个必须不为空:if(p==NULL || q==NULL){return false;}//3.两个数值一开始就不相等:if(p->val != q->val){return false;}return isSameTree(p->left,q->left)&& isSameTree(p->right,q->right);
}bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){//1.没有子树返回falseif(root==NULL)return false;//2.根节点的值相同有可能是相同子树的根节点:if(root->val == subRoot->val){if(isSameTree(root,subRoot)){return true;}}//进入递归(先序遍历):return isSubtree(root->left , subRoot)|| isSubtree(root->right , subRoot);
}

题目六:二叉树的前序遍历:

在这里插入图片描述
前序遍历:题目链接

方法一:

1.分析一下函数的参数和返回值:
1.返回一个数组的首地址(已经保存和前序遍历的数据)!
2.需要在堆区开辟空间这样才可以在外面找到这个数组的内容:
2.returnsize 返回数组的大小帮助外面去遍历数据:
3.使用计算节点个数的函数:

int TreeSize(struct TreeNode* root)
{return root==NULL? 0: TreeSize(root->left)+TreeSize(root->right)+1;
}void Traversal(struct TreeNode* root , int* tmp , int* i)
{if(root==NULL)return;tmp[*i]=root->val;(*i)++;Traversal(root->left , tmp , i);Traversal(root->right, tmp , i);
}int* preorderTraversal(struct TreeNode* root, int* returnSize){//1.开辟数组,返回顺序表长度int n=TreeSize(root);*returnSize = n;int* tmp=(int*)malloc(sizeof(int)*n);//2.给顺序表中添加内容:int i=0;Traversal(root , tmp , &i);return tmp;
}

拓展:

中序遍历:题目链接
后序遍历:题目链接

题目七:翻转二叉树:

请添加图片描述
翻转二叉树:题目链接

方法一:

1.不需要考虑左右子树为空的情况.
2.直接进行交换,下一次递归进入函数如果为空就会返回用了下一次函数判断当前为空的处理!
3.翻转是翻转每一颗树左右子树的根节点的情况!

请添加图片描述

void convert(struct TreeNode* root)
{if(root==NULL)return;struct TreeNode* tmp=NULL;tmp=root->left;root->left=root->right;root->right=tmp;convert(root->left);convert(root->right);
}struct TreeNode* invertTree(struct TreeNode* root){if(root==NULL)return root;convert(root);return root;
}

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

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

相关文章

透视俄乌网络战之二:Conti勒索软件集团(下)

透视俄乌网络战之一:数据擦除软件 透视俄乌网络战之二:Conti勒索软件集团(上) Conti勒索软件集团(下) 1. 管理面板源代码2. Pony凭证窃取恶意软件3. TTPs4. Conti Locker v2源代码5. Conti团伙培训材料6. T…

【Linux从入门到精通】多线程 | 线程互斥(互斥锁)

上篇文章我们对线程 | 线程介绍&线程控制介绍后,本篇文章将会对多线程中的线程互斥与互斥锁的概念进行详解。同时结合实际例子解释了可重入与不被重入函数、临界资源与临界区和原子性的概念。希望本篇文章会对你有所帮助。 文章目录 引入 一、重入与临界 1、1 可…

多线程|多进程|高并发网络编程

一.多进程并发服务器 多进程并发服务器是一种经典的服务器架构,它通过创建多个子进程来处理客户端连接,从而实现并发处理多个客户端请求的能力。 概念: 服务器启动时,创建主进程,并绑定监听端口。当有客户端连接请求…

GitLab使用的最简便方式

GitLab介绍 GitLab是一个基于Git版本控制系统的开源平台,用于代码托管,持续集成,以及协作开发。它提供了一套完整的工具,以帮助开发团队协同工作、管理和部署代码。 往往在企业内部使用gitlab管理代码,记录一下将本地代…

VR航天航空巡展VR科技馆航天主题科普设备沉浸遨游太空

每当飞机飞过头顶,我们总是忍不住抬头去仰望。从嫦娥奔月的神话传说,到莱特兄弟实现了上天翱翔的梦想,人类一直在不断探索更辽阔的天空和浩瀚的宇宙。 航空科普 寻梦而行 普乐蛙VR航天航空巡展,正在湖南郴州如火如荼的进行中&…

arm day2(9.15)数据操作指令,跳转指令,特殊功能寄存器指令,

作业 1.求最大公约数&#xff1a; .text .global _start _start:mov r0,#0x9mov r1,#0x15bl Loop Loop:cmp r0,r1 比较r0寄存器和r1寄存器的中的值beq stop 当两数相同时,退出程序subhi r0,r0,r1 r0>r1 r0 r0 - r1subcc r1,r1,r0 r0<r1 r1 r1 - r0mov pc,lr 恢复现…

【算法与数据结构】108、LeetCode将有序数组转换为二叉搜索树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;这道题给我们的是一个有序数组&#xff0c;并要求构成一个平衡二叉搜索树&#xff0c;二叉搜索树的很容…

CSS 之 grid 网格布局

一、简介 ​ display: grid;用于设置元素内部的布局类型为网格布局&#xff0c;其外显类型为块级元素。该类型的元素将内部分为行和列&#xff0c;划分成一个个单元格&#xff0c;并通过一系列相关属性控制单元格及其内容的布局和大小。 ​ 该属性值的主要应用场景为&#xf…

这个锂电池保护方案来自TIDA-010030

本篇博客只是作为个人记录&#xff0c;拆锂电池有危险&#xff0c;撬棒刺穿外壳可能爆炸&#xff0c;请勿模仿&#xff0c;误操作电池数据可能失效&#xff0c;请勿模仿。 1、简介 1.1、目的 得到该电池的电量计芯片型号、IIC从机地址、通信的实际波形&#xff1b; 1.2、步…

百度飞浆OCR识别表格入门python实践

1. 百度飞桨&#xff08;PaddlePaddle&#xff09; 百度飞桨&#xff08;PaddlePaddle&#xff09;是百度推出的一款深度学习平台&#xff0c;旨在为开发者提供强大的深度学习框架和工具。飞桨提供了包括OCR&#xff08;光学字符识别&#xff09;在内的多种功能&#xff0c;可…

Linux驱动IO篇——异步通知

文章目录 什么是异步通知异步通知和异步IO的区别信号含义应用层使用信号驱动如何实现异步信号驱动实例 什么是异步通知 异步通知在Linux的实现中是通过信号&#xff0c;而信号是在软件层次上对中断机制的一种模拟。这种机制和中断非常类似&#xff0c;所以可以以中断的思想来理…

重新认识交叉编译

1. 我以前对交叉编译的认知 引用正点原子的话来讲就是: 说得对&#xff0c;但是不全面&#xff0c;直到最近项目中遇到了一个例子我才重新认识什么是交叉编译。 2. build/host/target的概念 参考: Cross-Compilation (automake) 参考: Specifying Target Triplets (Autocon…

Python二级 每周练习题18

练习一: 从键盘输入任意字符串&#xff0c;按照下面要求分离字符串中的字符: 1、分别取出该字符串的第偶数位的元素(提醒注意:是按照从左往右数的方式确定字符串的位置) 2、并依次存储到一个列表中; 3、输出这个列表。 答案: ninput(请输入任意字符串:) #创建变量n存放用户…

数据结构入门 — 树的概念与结构

本文属于数据结构专栏文章&#xff0c;适合数据结构入门者学习&#xff0c;涵盖数据结构基础的知识和内容体系&#xff0c;文章在介绍数据结构时会配合上动图演示&#xff0c;方便初学者在学习数据结构时理解和学习&#xff0c;了解数据结构系列专栏点击下方链接。 博客主页&am…

外包干了2个月,技术退步明显。。。。。

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

【多线程】Thread 类 详解

Thread 类 详解 一. 创建线程1. 继承 Thread 类2. 实现 Runnable 接口3. 其他变形4. 多线程的优势-增加运行速度 二. Thread 类1. 构造方法2. 常见属性3. 启动线程-start()4. 中断线程-interrupt()5. 线程等待-join()6. 线程休眠-sleep()7. 获取当前线程引用 三. 线程的状态1. …

Buffer Pool

一.Buffer Pool的含义 Buffer Pool&#xff1a;缓冲池&#xff0c;简称BP&#xff0c;其作用是用来缓存表数据与索引数据&#xff0c;减少磁盘IO操作&#xff0c;提升效率。当Mysql执行查询的sql语句的时候&#xff0c;会先去缓存当中看是否有对应的数据&#xff0c;如果有则直…

显示器显示的画面突然偏红色如何解决

显示器显示的画面突然偏红色如何解决 1. 概述2. 解决方法结束语 1. 概述 显示器显示的画面突然偏红色 &#xff0c;使用向日葵远程电脑&#xff0c;看到的画面是正常的&#xff0c;但是显示器上的画面确还是骗红的&#xff0c;这时候就需要看一下是不是开启了系统也夜间模式&a…

四川百幕晟科技:提升店铺质量方法是什么?

抖店是抖音旗下的移动电子商务平台&#xff0c;为商家提供在线销售和促销的机会。在抖店&#xff0c;经验值是商家评价和信誉的重要指标之一。反映了平台上商户的服务质量和用户满意度。那么&#xff0c;如何查看自己在抖店手机上的体验分数呢&#xff1f; 1、如何查看抖店手机…

Eclipse 安装串口终端工具

Eclipse已集成串口终端显示&#xff0c;只需要我们自己下载安装即可使用。使用SSH连接也差不多。 查看eclipse版本信息 help->About Eclipse 查看version&#xff0c;我的是4.7.3a&#xff0c;记住代号&#xff0c;我的是“Oxygen”,下面有用。 安装eclipse自带的“Termin…