下面是今天的内容
二叉树OJ必刷题

1. 二叉树销毁
- 利用分而治之的思想可转化为:
- 子问题:左右子树的销毁。
- - 返回条件(最小规模子问题):左/右子树为空。
先销毁根再销毁左右——后序查找
实现
void destory(BTNode* root)
{
if (root == NULL)
{
return 0;
}
destory(root->left);
destory(root->right);
free(root);
//形参改变不会改变实参,故在函数外置空
}
2. 二叉树查找值为x的值
- 子问题:左/右子树是否为x
- 返回条件:
- 找到x返回该地址;
- 左子树找不到去右子树找;
- 右子树找不到返回空;
- 注意:要返回地址,所以每次栈帧销毁都要接收返回值,直到回归第一层。
实现
BTNode* FreeFind(BTNode* root,BTDataType x)
{
//遍历->找到后即返回在函数中接收->前序
if (root == NULL)
{
return;
}
if (root->val == x)
{
return root;
}
BTNode* ret = NULL;
ret = FreeFind(root->left, x);
if (ret)
return ret;
ret = FreeFind(root->right, x);
if (ret)
return ret;
return NULL; //左右都没找到
}
3. 相同的树
题目:100.相同的树
给你两棵二叉树的根节点
p
和q
,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
- 最小递归子问题:
- 遍历
- 根是否相同
- 左右子树是否相同
- 返回条件:
- 同时为空返回true(子树相同)
- 接下来有其中一端为NULL的情况,所以不可比较val
- 有一个为空返回flase
- 比较val是否相同,不相等则返回false
- 相同返回true
- 注意:在该题中要求子树末端也必须得相同
实现
/**
* 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);
}
4. 对称二叉树
- 题目:101对称二叉树
给你一个二叉树的根节点
root
, 检查它是否轴对称。
- 沿用上一题的方法,可以将其改为从第二层开始两子树的左右-右左子树相同的问题。
- 最小递归子问题:
- 左子树的左值是否等于右子树右值
- 左子树的右值是否等于右子树左值
- 返回条件:
- 全为空返回false;
- 相同返回true;
- 不满足子问题返回false;
实现
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);
}
5. 二叉树的前\中\后序遍历
给你二叉树的根节点
root
,返回它节点值的 前序 遍历。在线编程中属于接口型(另一个是io型,自己编程)
- 题目分析
int* returnSize
返回的是数组大小,形参的改变改变不了实参,故传递指针类型 。- 题目值类型为
int*
,由于开辟的空间名可自己定义,故返回数组名。- 我们在内部定义局部变量来放malloc过来的空间
开辟空间大小TreeSize- 将树中元素按前序放入数组中,中序后序遍历与前序同理(前序方法在另一篇文章中已经讲过,故不在此赘述前中后序)
5.最后将n赋值给*TreeSize并返回数组a;
实现
/**
* 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);
// a[(*pi)++]=root->val; //中序
preorder(root->right,a,pi);
// a[(*pi)++]=root->val; //后序
}
int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
int n=TreeSize(root);
int* a=(int*)malloc(sizeof(int)*n);
int j=0;
//不能重复malloc申请空间,所以写一个子函数用来递归
preorder(root,a,&j);
*returnSize=n;
return a;
}
6. 翻转二叉树
题目:翻转二叉树
- 给你一棵二叉树的根节点
root
,翻转这棵二叉树,并返回其根节点。
分析:最小递归子问题:左右两子树交换(Swap)
返回条件:将每个节点遍历完后是NULL返回。前序遍历
综上,该程序可大致理解为在前序遍历中的交换左右子树问题
实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
void Swap(struct TreeNode** p1,struct TreeNode** p2)
{
struct TreeNode* tmp=NULL;
tmp=*p1;
*p1=*p2;
*p2=tmp;
}
void PreOrder(struct TreeNode* root)
{
if(root==NULL)
return ;
Swap(&(root->left),&(root->right));
PreOrder(root->left);
PreOrder(root->right);
}
struct TreeNode* invertTree(struct TreeNode* root)
{
PreOrder(root);
return root;
}
7. 另一颗子树
- 题目: 另一颗子树
给你两棵二叉树
root
和subRoot
。检验root
中是否包含和subRoot
具有相同结构和节点值的子树。如果存在,返回true
;否则,返回false
。
二叉树tree
的一棵子树包括tree
的某个节点和这个节点的所有后代节点。tree
也可以看做它自身的一棵子树。
题目分析:
最小子问题:判断当前节点下的子树是否相等,见上文中100.相同的树 问题。
返回条件:
前序遍历每个节点,若相同则判断当下节点子树是否相等
实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool IsSameTree(struct TreeNode* root, struct TreeNode* subRoot)
{
//全为空
if(root==NULL && subRoot==NULL)
return true;
//一个为空
if(root==NULL || subRoot==NULL)
return false;
//都不为空
if(root->val != subRoot->val)
return false;
return IsSameTree(root->left,subRoot->left)
&& IsSameTree(root->right,subRoot->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
if(root == NULL)
return false;
if(root->val==subRoot->val)
{
if(IsSameTree(root,subRoot))
return true;
}
return isSubtree(root->left,subRoot)
|| isSubtree(root->right,subRoot);
}
8. 层序遍历——队列
先进先出
引入队列结构,将int
类型该为树的节点类型
.h在预处理阶段不会被处理。.h文件回去再.cpp文件展开,所以放在结构体声明下面
- 实现过程
root=1时,打印front=1,左右不为空,左2右3入队列,删除队头元素1
root=2时,打印front=2,左右不为空,左4右5入队列,删除队头元素2
root=3时,打印front=3,左右为空,删除队头元素3
root=4时,打印front=4,右不为空,右6入队列,删除队头元素4
………………
![[Drawing 2023-09-23 16.03.53.excalidraw.png]]
void LevelOrder(BTNode* root)
{
Que q;
QueInit(&q);
if (root)
QuePush(&q, root);
while (!QueEmpty(&q))
{
BTNode* front = QueFront(&q);
printf("%d",front->val);
if (front->left)
QuePush(&q, front->left);
if (front->right)
QuePush(&q, front->right);
QuePop(&q);
}
printf("\n");
QueDestory(&q);
}
9. 是否为完全二叉树
完全二叉树:前n-1层都是连续的(走层序遍历非空节点连续)
入到空后面一定没有非空
遍历,有空且后面没有非空时为完全二叉树。
bool TreeComplete(BTNode* root)
{
Que q;
QueInit(&q);
if (root)
QuePush(&q, root);
while (!QueEmpty(&q))
{
BTNode* front = QueFront(&q);
//全部入队列,直到遇到NULL停止
if (front==NULL)
break;
QuePush(&q, front->left);
QuePush(&q, front->right);
QuePop(&q);
}
//继续入队,遇到非空即不是完全二叉树
while (!QueEmpty(&q))
{
BTNode* front = QueFront(&q);
QuePop(&q);
if (front != NULL)
{
QueDestory(&q);
return false;
}
}
QueDestory(&q);
return true;
}
10. 求树的高度
高度——就是最深的一层
//(1)
int treeheight(btnode* root)
{
if (root == null)
return 0;
return treeheight(root->left) > treeheight(root->right) ?
treeheight(root->left) + 1 : treeheight(root->right) + 1;
}
//多次调用计算,效率及其地下低下,因为在调用时进行了两次递归,非常差
//(2)
int Treeheight(BTNode* root)
{
if (root == NULL)
return 0;
int leftheight = Treeheight(root->left);
int rightheight = Treeheight(root->right);
return leftheight > rightheight ? leftheight + 1 : rightheight + 1;
}
//(3)
int Treeheight(BTNode* root)
{
if (root == NULL)
return 0;
return fmax(Treeheight(root->left),Treeheight(root->right)) + 1;
}
fmax记得包含头文件
#include<math.h>
11. [KY11 二叉树遍历]
题目 11. KY11 二叉树遍历
分析
- 根据题目要求,对字符串先序遍历(根-左-右)创建二叉树,如图所示;
- 当遇到空
#
时为空,返回NULL
- 之后按照后续遍历将二叉树打印出来
代码
#include <stdio.h>
#include <stdlib.h>
typedef char BTDataType;
//二叉树结构体
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
BTDataType val;
}BTNode;
//创建树结构
BTNode* CreatTree(char* str, int* pi)
{
if (str[*pi] == '#')
{
(*pi)++;
return NULL;
}
BTNode* root = (BTNode*)malloc(sizeof(BTNode));
root->val = str[*pi];
(*pi)++;
//先序插入
root->left = CreatTree(str, pi);
root->right = CreatTree(str, pi);
return root;
}
//中序输出
void Inorder(BTNode* root)
{
if (root == NULL)
return;
Inorder(root->left);
printf("%c ", root->val);
Inorder(root->right);
}
int main()
{
char str[100];
scanf("%s", str);
int i = 0;
BTNode* root = CreatTree(str, &i);
//输入下标地址,便于在函数递归调用时可以使用
Inorder(root);
return 0;
}
感谢未来大佬们的光顾,创作不易,还请给个免费的赞哦~~❤️❤️❤️