十道题带你手撕二叉树

点击蓝字

2e352373ec02f71a3ead6f807caebe03.png

关注我们

1、单值二叉树

题目:

e3f6b1f8fe9f6fe29a73b113725de22a.png

思路一:(遍历的方法)

将根节点的值与二叉树中的每一个节点存储的val值进行比较,如果不同就返回false,如果全部相同,就返回true。

代码:

bool _isUnivalTree(struct TreeNode*root,int num)//辅助函数
{
if(root == NULL)//只有一个节点或者递归调用到叶子节点的字节点时
return true;
else if(root->val == num)//当前根节点的值与存储的初始根节点的num相同的时候,此时就不需要返回true,因为当前根节点存储的值与初始节点存储的值相同并不代表后续节点的值也相同{
return _isUnivalTree(root->left,num) && _isUnivalTree(root->right,num);}
else//此情况就是root->val!=num的时候
return false;
}
bool isUnivalTree(struct TreeNode* root)
{
return _isUnivalTree(root,root->val);//调用辅助函数
}

思路二:

判断当前根节点的值是否与其左右子节点的值相等,如果不相等就返回false,同样,如果递归调用到了节点为空节点时就返回true。

代码:

bool isUnivalTree(struct TreeNode* root)
{
//空树复合题目的要求
if(root==NULL){
return true;}//判断根节点与其左右子节点是否一样
if(root->left&&root->left->val!=root->val){
return false;}
if(root->right&&root->right->val!=root->val){
return false;}//判断左右子树
return isUnivalTree(root->left)&&isUnivalTree(root->right);
}

问:为什么只需要判断根节点和左右子节点是否一样就可以了?

答:注意这个-传递性,如果根节点和其左右子节点分别相同了,那么在递归的时候,之前的左右子节点就会变成根节点,此时就是在保持前面一样的前提下来判断新的根节点和新的根节点的左右子节点是否相同,优点类似链表,就是说链表的第一和第二个节点是相同的之后,然后判断第二和第三个节点是否是相同的,如果第二和第三个节点是相同的之后,那么第一和第三个节点也必然是相同的,依此类推,当这样的每个比较都成立之后,就说明整个二叉树就是等值二叉树。

当然,还有一种不是很好的写法,这种写法虽然也能通过,和上面的思路来说本质上并没有太大的区别(甚至定义的那个全局变量还显得有些多余),并不推荐这种写法,因为这种写法定义了一个全局变量,在OJ题中最好不要定义全局变量和静态变量,因为后台程序可能会多次调用这个程序,flag中可能还存储着上一次的结果,在下一次调用时容易出问题。

代码如下:

bool flag = true;//默认最开始就是单值二叉树
bool isUnivalTree(struct TreeNode* root){
if(root==NULL){flag = true;
return flag;}if(root->left && root->val!=root->left->val){flag = false;
return flag;}
if(root ->right &&root->val!=root->right->val ){flag = false;
return flag;}
return isUnivalTree(root->left)&&isUnivalTree(root->right);
}

2、相同的树

题目:

f36213726c0b4c8d50a1b8eb74e8c6de.png

代码:

bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
//都是空树
if(p==NULL&&q==NULL)
return true;//有一个为空
if(p == NULL || q == NULL)
return false;//都不为空
if(p->val!=q->val)
return false;//递归比较左右子树
return isSameTree(p->left, q->left)&&isSameTree(p->right, q->right);
}

3、对称二叉树

题目:

8d97239822e77ce34f6189a63d680fc8.png

代码:

bool isSymmetricTree(struct TreeNode* p,struct TreeNode* q)//辅助函数
{
//两个节点均为空的情况
if(p==NULL && q==NULL){
return true;}//两个节点有一个不为空的情况
if(p == NULL || q == NULL){
return false;}//两个节点是否相等的情况并对两个节点进行递归判断,注意镜像相反
return p->val == q->val && isSymmetricTree(p->left,q->right)&&isSymmetricTree(p->right,q->left);
}bool isSymmetric(struct TreeNode* root){
//根节点为空的情况
if(root == NULL){
return true;}//根节点不为空的情况
return isSymmetricTree(root->left,root->right);
}

4、二叉树的前序遍历

题目:

48f9721ba55e51f7532ad7c83f314839.png

代码:

int BTreeSize(struct TreeNode* root)//计算二叉树元素的数目
{
return root == NULL ? 0 : 1 + BTreeSize(root->left) + BTreeSize(root->right);
}void _preorder(struct TreeNode* root,int *a,int *i)//辅助函数
{
if(root == NULL)//空的时候直接返回{
return;}
//1.先遍历根节点a[*i] = root->val;//将有值得存储到开辟得数组空间中(*i)++;//数组下标进行自增操作
//2.遍历左子树_preorder(root->left,a,i);//对左子树进行操作
//3.遍历右子树_preorder(root->right,a,i);//对右子树进行操作
}int* preorderTraversal(struct TreeNode* root, int* returnSize){
int count = BTreeSize(root);//计算题目所给二叉树元素得数目
int *a = malloc(sizeof(int)*count);//开辟数组存储二叉树元素assert(a);//防止malloc开辟失败*returnSize = count;//存储数组元素得数目
int i = 0;//当作数组下标来存储二叉树元素_preorder(root,a,&i);
return a;
}

5、二叉树的中序遍历

题目:

41c2e6b1b9960540aa00ce03aa47eee7.png

代码:

int BTreeSize(struct TreeNode* root)//计算二叉树元素的数目
{
return root == NULL ? 0 : 1 + BTreeSize(root->left) + BTreeSize(root->right);
}void _inorder(struct TreeNode* root,int *a,int *i)//辅助函数
{
if(root == NULL)//空的时候直接返回{
return;}
//1. 遍历左子树_inorder(root->left,a,i);//对左子树进行操作
//2.遍历根节点a[*i] = root->val;//将有值得存储到开辟得数组空间中(*i)++;//数组下标进行自增操作
//3.遍历右子树_inorder(root->right,a,i);//对右子树进行操作}int* inorderTraversal(struct TreeNode* root, int* returnSize){
int count = BTreeSize(root);//计算题目所给二叉树元素得数目
int *a = malloc(sizeof(int)*count);//开辟数组存储二叉树元素assert(a);//防止malloc开辟失败*returnSize = count;//存储数组元素得数目
int i = 0;//当作数组下标来存储二叉树元素_inorder(root,a,&i);
return a;
}

6、二叉树的后序遍历

2d0696403785762b880c7504f447854d.png

代码

int BTreeSize(struct TreeNode* root)//计算二叉树元素的数目
{
return root == NULL ? 0 : 1 + BTreeSize(root->left) + BTreeSize(root->right);
}void _postorder(struct TreeNode* root,int *a,int *i)//辅助函数
{
if(root == NULL)//空的时候直接返回{
return;}
//1. 遍历左子树_postorder(root->left,a,i);//对左子树进行操作
//2.遍历右子树_postorder(root->right,a,i);//对右子树进行操作
//3.遍历根节点a[*i] = root->val;//将有值得存储到开辟得数组空间中(*i)++;//数组下标进行自增操作
}int* postorderTraversal(struct TreeNode* root, int* returnSize){
int count = BTreeSize(root);//计算题目所给二叉树元素得数目
int *a = malloc(sizeof(int)*count);//开辟数组存储二叉树元素assert(a);//防止malloc开辟失败*returnSize = count;//存储数组元素得数目
int i = 0;//当作数组下标来存储二叉树元素_postorder(root,a,&i);
return a;
}

7、另一棵树的子树

3786b2e95e9bce7886224964146abf93.png

代码:

bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
//都是空树
if(p==NULL&&q==NULL)
return true;//有一个为空
if(p == NULL || q == NULL)
return false;//都不为空
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){
if(root == NULL)
return false;
return isSameTree(root,subRoot) || isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}

8、二叉树的遍历

题目

6afd8e46741249b5e8023feca381ffdf.png

代码:(思路仍然是利用递归的思想)

#include<stdio.h>
#include<stdlib.h>
typedef struct BTreeBode
{
char data;
struct BTreeNode*left;
struct BTreeNode*right;
}BTNode;BTNode* CreateTree(char *a,int *pi)
{
if(a[*pi]== '#'){(*pi)++;
return NULL;}BTNode* root = malloc(sizeof(BTNode));//创建节点root->data = a[(*pi)++];root->left = CreateTree(a,pi);root->right = CreateTree(a,pi);return root;
}
void InOrder(BTNode* 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;BTNode* tree = CreateTree(str,&i);InOrder(tree);
return 0;
}

9、翻转二叉树

思路:是利用递归的思想,就是将每个二叉树看成是左子树 + 根节点 + 右子树
左子树又可以看成是:左子树 = 左子树 + 根节点 + 右子树
右子树又可以看成是:右子树 = 左子树 + 根节点 + 右子树

然后将左右子树分别互换即可,从最小的子树开始思考:

175014b283941453a56fbbaf59a530e3.png

上面的子树中,2有两个子节点3和1,所以将3节点和1节点进行互换即可,然后对于整个二叉树来说,也都是将左子树和右子树进行互换即可。

edc4b88212c7767cbb1db36a2cc7076f.png

代码

struct TreeNode* invertTree(struct TreeNode* root){
if(root == NULL)//空指针时返回{
return NULL;}
struct TreeNode* left = invertTree(root->left);//左子树
struct TreeNode* right = invertTree(root->right);//右子树root->left = right;root->right = left;
return root;
}

10、二叉树的销毁

注意:二叉树的销毁只能采取后序遍历的方式进行销毁,因为一旦根节点被销毁后,就无法找到子节点的地址了。

void BinaryTreeDestory(BTNode** root)
{
if ((*root) == NULL)//判断是否为空,如果为空直接返回{
return;}
//此处采用后序遍历的方法,因为根必须留在最后销毁BinaryTreeDestory(&((*root)->left));BinaryTreeDestory(&((*root)->right));
free(*root);*root = NULL;
}

*声明:本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

a03a0244b8a43e7c2f5d4c9f3e81ddd4.png

166aeeba85a39f818791dfd5943fa821.gif

戳“阅读原文”我们一起进步

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

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

相关文章

C语言实现面向对象编程 : 封装、继承、多态

点击蓝字关注我们不知道有多少人去了解过语言的发展史&#xff0c;早期C语言的语法功能其实比较简单。随着应用需求和场景的变化&#xff0c;C语言的语法功能在不断升级变化。虽然我们的教材有这么一个结论&#xff1a;C语言是面向过程的语言&#xff0c;C是面向对象的编程语言…

图解python pdf_Python合并同一个文件夹下所有PDF文件的方法

一、需求说明 下载了网易云课堂的吴恩达免费的深度学习的pdf文档&#xff0c;但是每一节是一个pdf&#xff0c;我把这些PDF文档放在一个文件夹下&#xff0c;希望合并成一个PDF文件。于是写了一个python程序&#xff0c;很好的解决了这个问题。 二、数据形式三、合并效果四、py…

用C语言实现状态机设计模式

点击蓝字关注我们状态机模式是一种行为模式&#xff0c;在 《设计模式》 这本书中对其有详细的描述&#xff0c;通过多态实现不同状态的调转行为的确是一种很好的方法&#xff0c;只可惜在嵌入式环境下&#xff0c;有时只能写纯C代码&#xff0c;并且还需要考虑代码的重入和多任…

这几行代码,惊为天人!

点击蓝字关注我们事情是这么一回事&#xff1a;国外有个大佬在StackExchange上发起了一个叫做 Tweetable Mathematical Art 的比赛。参赛者需要用C编写代表三原色的RD、GR、BL三个函数&#xff0c;每个函数都不能超过 140 个字符。每个函数都会接到 i 和 j 两个整型参数&#x…

快速搞定C/C++ 的条件编译

点击蓝字关注我们1、条件编译的时机我们都知道vscode其实是一个编辑器&#xff0c;你要在上面跑C或者C你需要配置编译器&#xff0c;拿编译器是怎样吧一个文本文件变成一个可执行文件的呢&#xff1f;那必然是经历以下这四步预处理&#xff1a;宏替换&#xff0c;头文件的展开&…

python连接不上数据库_pycharm连接mysql数据库连接不上

代码其实很简单&#xff0c;只有一小段&#xff0c;是在pycharm上运行的&#xff0c;所用的python版本为2.7&#xff0c;mysql版本为5.7.21 # -*- coding: UTF-8 -*- import re import MySQLdb if __name__ __main__: #打开数据库 conn MySQLdb.connect(hostlocalhost,port33…

assertj_AssertJ的SoftAssertions –我们需要它们吗?

assertj编写好的单元测试的规则之一是&#xff0c;它应该由于一种原因而失败&#xff0c;因此&#xff0c;单元测试应该测试一种逻辑概念。 有时很难在每个测试中拥有一个断言。 为了遵循规则&#xff0c;我们可能在单个测试中每个对象具有多个断言。 但是&#xff0c;在一个测…

用C/C++语言代码实现一个虚拟机

点击蓝字关注我们本文将教你编写一个自己的虚拟机&#xff08;VM&#xff09;&#xff0c;这个虚拟机能够运行汇编语言编写的程序&#xff0c; 例如我朋友编写的 2048 或者我自己的 Roguelike。如果你会编程&#xff0c;但希望 更深入地了解计算机的内部原理以及编程语言是如何…

C++—vector的使用

点击蓝字关注我们一、vector的介绍说的简单点&#xff1a;vector是可以动态增长的数组容器vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。…

python词频统计完整步骤_Python中文文本分词、词频统计、词云绘制

本文主要从中文文本分词、词频统计、词云绘制方面介绍Python中文文本分词的使用。会使用到的中文文本处理包包括&#xff1a;wordcloud,jieba&#xff0c;re&#xff08;正则表达式&#xff09;,collections。 1 准备工作 导入相关的包&#xff0c;读取相关数据。 #导入包 impo…

现代 C++ 测试工具链

点击蓝字关注我们gtest的问题gtest需要安装有时候带来很多不方便&#xff0c;比如需要经常切换gcc和clang的时候就比较麻烦&#xff0c;安装的gtest可能在另一个编译器下编译不过, 编写跨平台程序的时候需要多次安装gtest&#xff0c;非常不便。另外一个问题是网络原因&#xf…

数据结构压缩_将数据压缩到数据结构中

数据结构压缩这个故事是关于我们最近在Plumbr进行的容量优化任务。 一切始于将无害的要求添加到现有组合中。 您可能知道&#xff0c;Plumbr监视解决方案作为连接到服务器的Java代理分发。 只需少量添加即可跟踪一段时间内所有已连接的代理&#xff0c;以便可以实时回答以下问…

swing 状态视图分离_Java Swing模型视图适配器介体

swing 状态视图分离通常&#xff0c;我基于Spring Framework构建Java应用程序。 但是&#xff0c;最近有人要求我使用与语言无关的MVC框架PureMVC为客户端实现Java桌面应用程序&#xff0c;因此以下是我在Java Swing中为PureMVC进行员工管理展示的演示实现。 如果您想继续学习&…

超级炫酷的C语言技巧!

点击蓝字关注我们C语言常常让人觉得它所能表达的东西非常有限。它不具有类似第一级函数和模式匹配这样的高级功能。但是C非常简单&#xff0c;并且仍然有一些非常有用的语法技巧和功能&#xff0c;只是没有多少人知道罢了。一、指定的初始化很多人都知道像这样来静态地初始化数…

webgl 基础渲染demo_WebGL + ThreeJS 实现实时水下焦散 Part 1

知乎视频​www.zhihu.com采用 WebGL 和 ThreeJS 运行实时焦散运算&#xff0c;需要一点相关基础。本文主要介绍焦散的原理以及计算方法原作者https://github.com/martinRenou​github.com代码和原文https://github.com/martinRenou/threejs-caustics​github.com由于本人的笔电…

超硬核C++BestPractices翻译与阅读笔记

点击蓝字关注我们硬货开始这本书的副标题是&#xff1a;45ish Simple Rules with Specific Action items for better C ,这本书是由大佬推荐的&#xff0c; C学习有必要掌握一下这45条最佳实践&#xff0c; 可以很大程度上提升代码的可读性和健壮性&#xff0c; 而且这本书也不…

diskgenius单文件专业版_金蝶KIS专业版系列——系统工具六(业务套打工具)

导读&#xff1a;&#xff08;一&#xff09;问一问1.1.套打的作用1.2.举例&#xff08;二&#xff09;怎么进入套打设计器2.1.入口12.2.入口2&#xff08;三&#xff09;怎么使用套打设计器打开套打模板3.1.打开系统标准套打模板3.2.新建一个空白的套打模板3.3.保存套打模板3.…

面试常问的16个C语言问题,你全会吗?

点击蓝字关注我们金三银四不少小伙伴在找工作&#xff0c;这里我给大家分享一下面试中经常会遇到的一些嵌入式C语言问题&#xff0c;你看看能做到全会吗&#xff1f;1、用预处理指令#define 声明一个常数&#xff0c;用以表明1年中有多少秒&#xff08;忽略闰年问题&#xff09…

高性能 高可用 可弹性伸缩_性能,可伸缩性和活力

高性能 高可用 可弹性伸缩本文是我们名为Java Concurrency Essentials的学院课程的一部分。 在本课程中&#xff0c;您将深入探讨并发的魔力。 将向您介绍并发和并发代码的基础知识&#xff0c;并学习诸如原子性&#xff0c;同步和线程安全性的概念。 在这里查看 &#xff01;…

iptables命令_程序员最有用的linux命令汇总

总结程序员在工作中&#xff0c;最有用的linux命令如下&#xff1a;1、vi/vim 我们须要在服务器上代码一些代码时候&#xff0c;就用vi/vim命令就可以&#xff0c;vim是vi的升级&#xff0c;本色自带代码高亮工具&#xff0c;利于查看。dd 删除光标所在行o 向光标所在行向下增加…