二叉树OJ题目

一.二叉树第k层结点个数

有这样的一个思路:我既然要求第k层的结点个数,我肯定是要用到递归,那么当我在递归到第k层的时候我就开始判断,这一层是不是我所需要的那一层,如果是,就计数有几个节点,如果不是,就继续递归。就像这个图:

我们在往下递归的时候,我们的k也随之递减,当k为1的时候,这里就是我们要求的那一层。 

int BinaryTreeLevelKSize(BTNode* root, int k)
{if (root == NULL)return 0;if (k == 1)return 1;return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}

二.二叉树查找值为x的结点

这个要处理的细节就比较多了

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL)return NULL;if (root->data = x)return root;BTNode* ret1 = BinaryTreeFind(root->left, x);if (ret1)//如果ret1不为NULL就说明找到了return ret1;BTNode* ret2 = BinaryTreeFind(root->right, x);if (ret2)//与ret1同理return ret2;return NULL;//最底层的叶子结点找完了,依然没有符合的,返回NULL
}

在这个函数中依旧是需要不断的递归,首先是一直往左子树走,如果没有找到,就要一直到左子树为空树,然后再去右子树找,层层递进。要注意的是当我们在往左子树和右子树递归的时候,我们一定要把值给记录下来再去返回。

如图所示,我们要去找6的话:

三.对称二叉树

OJ链接:对称二叉树

这道题依旧是递归的思想 

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/
bool _isSymmetric(struct TreeNode* root1,struct TreeNode* root2)
{if(root1==NULL&&root2==NULL)return true;//如果两个都是空树,就说明这个结点是对称的if(root1==NULL||root2==NULL)return false;//上面的if已经排除了两个都是空树的情况,如果这个成立,说明必有一个不是空树,则就是不对称的if(root1->val!=root2->val)return false;//两棵树都不是空树,就比较它们的值,注意不能用两值相等作为判断条件,因为如果相等就返回的话,后面的结点就比不了了return _isSymmetric(root1->left,root2->right)&&_isSymmetric(root1->right,root2->left);//最后就递归,左树的左子树要跟右树的右子树相等,左树的右子树要跟右树的左子树相等
}
bool isSymmetric(struct TreeNode* root) {return _isSymmetric(root->left,root->right);
}

注意看注释。

四.二叉树的前序遍历

OJ题目链接:二叉树的前序遍历

看一下我上一篇博客理解了,这个相对于其他的OJ是比较简单的: 

/*** 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)//这个函数用来返回树里的全部结点个数{return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;}
void PreOrder(struct TreeNode* root,int* a,int* pi)//这个函数就是前序遍历
{if(root==NULL)//为空了就结束,返回到上一层return;a[(*pi)++]=root->val;//先把根的值一个一个的往数组里送PreOrder(root->left,a,pi);//然后是左子树PreOrder(root->right,a,pi);//右子树
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {*returnSize=TreeSize(root);int* a=(int*)malloc(sizeof(int)*(*returnSize));//右多少个结点我们就开多少的空间int i=0;PreOrder(root,a,&i);//前序遍历return a;//把数组返回
}

 五.相同的树

OJ链接:相同的树

 这个其实就跟上面的那个对称二叉树有异曲同工之妙,只是换了一下对比的方向。看一下上面的代码,这个也就十分的好理解。

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);
}

六.另一棵树的子树 

OJ链接:另一棵树的子树 

 

注意一下这个题是在上一个判断相同的树的基础上去做的

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/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)//如果树为NULL就不可能是子树return false;if(root->val==subRoot->val&&isSameTree(root,subRoot))//判断一下根的值相不相等,如果相等判断一下这两个树是不是一样的return true;return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);//然后在这里开始遍历
}

 七.二叉树的构建及遍历

OJ链接:二叉树的构建及遍历

这道题就是把二叉树的构建和遍历整合到一起 

#include <stdio.h>
#include<stdlib.h>
typedef struct BTNode
{struct BTNode* left;struct BTNode* right;char val;
}BTNode;
BTNode* CreatTree(char* a,int* pi)
{if(a[*pi]=='#')//如果是#就说明这个结点为空树{(*pi)++;//数组往后走return NULL;}BTNode* root=(BTNode*)malloc(sizeof(BTNode));//动态开辟一块内存root->val=a[(*pi)++];//这个是根,把数组的值给根root->left=CreatTree(a,pi);//然后从左子树开始递归root->right = CreatTree(a,pi);//这里到右子树return root;
}
void InOrder(BTNode* root)//这里还要写一个中序遍历
{if(root==NULL){return;}InOrder(root->left);printf("%c ",root->val);InOrder(root->right);
}
int main()
{char a[100];scanf("%s",a);int i=0;BTNode* root=CreatTree(a, &i);InOrder(root);return 0;
}

这个就是这个题的过程。

如果只看上图不能理解的话看一下下面的代码遍历: 

 

 八.二叉树的销毁

二叉树的销毁就十分简单了,只需要记住一个点,因为我们要用到递归,根要放到最后销毁,如果提前销毁了就会导致找不到左右子树。

void BTDestory(BTNode* root)
{if (root == NULL){return;}BTDestory(root->left);BTDestory(root->right);free(root);
}

九.判断二叉树是否为完全二叉树(层序遍历)

解决这个题我们用层序遍历的话会很好写。

首先先说一下层序遍历:

设二叉树的根结点所在 层数为1,层序遍历就是从所在二叉树的根结点出发,首先访问第一层的树根结点,然后从左到右访问第2层 上的结点,接着是第三层的结点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

简单的说,我们遍历的顺序是这样的:

要实现这个,我们可以用一下队列。

先构建结构体二叉树:

typedef struct BTNode
{struct BTNode* left;struct BTNode* right;char val;
}BTNode;

这个是队列的实现:

特别注意一下第一行的代码,我构建的队列里面的值是指针

typedef struct BTNode* QDataType;typedef struct QueueNode
{struct QueueNode* next;QDataType a;
}QNode;
typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}
void QueueDestroy(Queue* pq)
{assert(pq);QNode* pcur = pq->phead;while (pcur){QNode* next = pcur->next;//把下一个节点提前保存起来free(pcur);pcur = next;//指针往后移动}pq->phead = pq->ptail = NULL;//全部释放完毕后注意指针也要置为NULLpq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("QueuePush::malloc");return;}newnode->a = x;newnode->next = NULL;if (pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = pq->ptail->next;}pq->size++;
}
void QueuePop(Queue* pq)
{assert(pq);assert(pq->size != 0);// 一个节点if (pq->phead->next == NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}else // 多个节点{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->a;
}
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}

 然后就是正式的层序遍历:

void LevelOrder(BTNode* root)
{Queue q;QueueInit(&q);//初始化队列if (root)//如果根不为空,就入队列里面QueuePush(&q, root);while (!QueueEmpty(&q))//循环是等到队列完全没有值了跳出循环{BTNode* front = QueueFront(&q);//提出队头的值QueuePop(&q);//删除队头printf("%d ", front->val);//打印二叉树的根结点的值if (front->left)//如果左子树不为空,就把左子树入到队列里QueuePush(&q, front->left);if (front->right)//同理,如果右子树不为空,就把右子树入到队列里QueuePush(&q, front->right);}QueueDestroy(&q);
}

知道了层序遍历,我们就可以做这道题目了:

我们知道,关于完全二叉树它的最后一层的结点一定是顺序存放的。所以我们就可以利用层序遍历往后走,即使遇到空也进队列。当我们遇到第一个空结点时,我们就开始判断,如果后面全是空这棵树就是完全二叉树,反之不是。

bool BTComplete(BTNode* root)
{Queue q;QueueInit(&q);if (root)QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);if (front == NULL)//如果刚好是一个完全二叉树,那么这里为NULL了就说明所有的结点都遍历完毕{break;//直接跳出循环}QueuePush(&q, front->left);QueuePush(&q, front->right);}while (!QueueEmpty(&q))//这个循环就是用来判断后面有没有非空节点,有的话就不是完全二叉树{BTNode* front = QueueFront(&q);if (front)//进入这个if语句就说明找到了非空的结点,就不是完全二叉树{QueueDestroy(&q);return false;}}QueueDestroy(&q);return true;
}

可以带入图看一下:

到这里这些题目就完全结束了,当然二叉树还没有结束,我现在这个程度,二叉树差不多到这里就是极限了。感谢大家的观看,如有错误还请多多指出。

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

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

相关文章

边框渐变样式

实现样式&#xff1a; 对应代码&#xff1a; div {min-height: 40vh;border: 10px solid transparent;background-image: linear-gradient(#222, #222), var(--gradient);background-origin: border-box;background-clip: padding-box, border-box;border-radius: 10px;positi…

粉丝问,有没有UI的统计页面,安排!

移动应用的数据统计页面具有以下几个重要作用&#xff1a; 监控业务指标&#xff1a;数据统计页面可以帮助用户监控关键业务指标和数据&#xff0c;例如用户活跃度、销售额、转化率等。通过实时更新和可视化呈现数据&#xff0c;用户可以及时了解业务的整体状况和趋势。分析用…

每日练习之字符串——得分

得分 题目描述 运行代码 #include <iostream> using namespace std; int main(){int n;cin>>n;while(n--){string s;cin>>s;int ls.length();int a0;int t1;for(int i0;i<l;i){if(s[i]O){at;t;}else if(s[i]X){t1;}}cout<<a<<endl;} } 代码…

QT7_视频知识点笔记_5_线程,数据库

多线程 两种办法&#xff1a;第一种&#xff1a;Qt4.7之前的线程使用的方法&#xff08;简单&#xff09;&#xff1b;第二种&#xff1a;Qt4.7之后的&#xff08;灵活–推荐&#xff09;----connect最后一个参数的作用&#xff1a;默认连接&#xff0c;队列连接&#xff0c;直…

操作系统总结4----死锁的处理策略总结

目录 2.4.2 死锁的处理策略-----预防死锁 &#xff08;1&#xff09;知识总览 &#xff08;2&#xff09;破环互斥条件 &#xff08;3&#xff09;破环不剥夺条件 &#xff08;4&#xff09;破环求情和保持条件 &#xff08;5&#xff09;破环循环等待条件 总结 2.4.3 死…

AI革命:生活无处不智能

AI革命&#xff1a;生活无处不智能 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &#x1f31d;分享学习心得&#xff0…

使用FFmpeg推流实现在B站24小时点歌直播

使用FFmpeg推流实现在B站24小时点歌直播 本文首发于个人博客 安装FFmpeg centos7 https://www.myfreax.com/how-to-install-ffmpeg-on-centos-7/ https://linuxize.com/post/how-to-install-ffmpeg-on-centos-7/ 使用FFmpeg在B站直播 https://zhuanlan.zhihu.com/p/2395…

竞赛 基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别

文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…

FreeRTOS任务间通信“IPC”

---------------信号量--------------- 信号量的定义&#xff1a; 操作系统中一种解决问题的机制&#xff0c;可以实现 “共享资源的访问” 信号&#xff1a;起通知作用量&#xff1a;还可以用来表示资源的数量当"量"没有限制时&#xff0c;它就是"计数型信…

C++原创人工智能QPBS01G大功告成!!!

俗话说得好&#xff0c;你周五周六不写作业&#xff0c;要上学了才着急了 我之前的版本bug太多&#xff0c;结果这两天晚上改的我两眼发白&#xff0c;太烦人了 这次这娃学聪明了&#xff0c;遇到不会的问题上网搜&#xff0c;我还更新了反骂人骂人功能&#xff0c;第一次测试…

抖音小店新规又来了!平台下调了两项门槛,惊掉商家下巴!

大家好&#xff0c;我是电商糖果 平台这几年为了快速发展电商项目&#xff0c;一直在向商家释放友好政策&#xff0c;目的就是为了吸引更多的商家入驻。 这不官方5月30日起下调了两个门槛&#xff0c;让不少商家大呼不可思议。 第一个就是保证金下调。 平台按照商家经营类目…

ProxySQL路由策略实现读写分离

目的&#xff1a;配置proxysql路由策略后将不同用户的不同请求路由到不同的节点&#xff0c;实现读写分离 前提条件&#xff1a; 配置表mysql_replication_hostgroups&#xff0c;10为写组&#xff0c;20为读组 mysql_users表中已添加用户writer用户加入10写组&#xff0c;rea…

【QT八股文】系列之篇章3 | QT的多线程以及QThread与QObject

【QT八股文】系列之篇章3 | QT的多线程 前言4. 多线程为什么需要使用线程池线程池的基础知识python中创建线程池的方法使用threading库队列Queue来实现线程池使用threadpool模块&#xff0c;这是个python的第三方模块&#xff0c;支持python2和python3 QThread的定义QT多线程知…

下一代Docker会让部署更丝滑吗

下一代Docker会让部署更丝滑吗 如何通俗易懂的理解DockerDocker有什么缺点Docker与AI结合&#xff0c;会让部署更加丝滑吗 随着互联网技术的不断发展&#xff0c;单机系统已经无法满足日益正常的用户量以及正常处理用户请求&#xff0c;这个时候就需要进行多机部署&#xff0c;…

k8s-helloword部署一个应用

k8s-helloword部署一个应用 快速部署一个pod命令 部署一个名为 test-nginx Pod 方式一&#xff1a;使用 kubectl run kubectl run test-nginx --imagenginx然后使用 kubectl get pod 查看&#xff0c;kubectl get pod 是查看默认名称空间下的Pod 如果想要跟详细的查看这个…

四元数学习总结(1)

导语&#xff1a;相比矩阵&#xff0c;用四元数处理3D旋转的优势是毋庸置疑的&#xff0c;但由于概念复杂&#xff0c;难于理解&#xff0c;一直令我摸不着头脑。最近学习更是发现在机器人、无人机、SLAM等先进领域&#xff0c;四元数被当成实数、整数这样的基础&#xff0c;所…

SQLiteOpenHelper数据库帮助器

SQLiteOpenHelper数据库帮助器是Android提供的数据库辅助工具。 1、继承SQLiteOpenHelper类&#xff0c;需要重写onCreate和onUpgrade两个方法 案例&#xff1a;实现增删改查 package com.example.databases_text;import android.app.PictureInPictureParams; import androi…

FPGA 纯逻辑arinc818 ip core

1、 符合FC-FS、FC-AV、FC-ADVB协议规范&#xff1b; 2、符合ARINC818协议规范&#xff1b; 3、支持光纤通信Class1、Class3服务&#xff1b; 5、可动态配置光纤端口速率&#xff0c;支持1.0625Gbps、2.125Gbps、3.1875Gbps、4.25Gbps可配置&#xff1b; 6、DDR控制接口简洁…

企业级架构及本体论最新进展

本文主要探讨了企业级架构和本体论的新兴趋势&#xff0c;特别是DoDAF、IDEAS、UAF和NAF的发展历程、理论基础、模型构建以及与ArchiMate和语义网技术的关联。原文: The emerging landscape of Enterprise Architecture and Ontology 导言 动机和采用的方法 关注我的人都知道我…

如何修复 System has not been booted with systemd 报错信息?

如何修复 System has not been booted with systemd 报错信息&#xff1f; 一、问题描述&#xff1a; 我们在学习 linux 系统时&#xff0c;使用 systemd 命令&#xff08;比如 sudo systemctl status ssh&#xff09;&#xff0c;可能会遇到一个报错信息&#xff1a; System…