文章目录
[4. 二叉树的遍历](#4. 二叉树的遍历)
[4.1 二叉树的前序遍历](#4.1 二叉树的前序遍历)
[4.2 中序遍历](#4.2 中序遍历)
[4.3 后序遍历](#4.3 后序遍历)
[5. 翻转二叉树](#5. 翻转二叉树)
[6. 平衡二叉树](#6. 平衡二叉树)
前言
上一篇文章主要补充了链式二叉树的一些性质还有部分功能实现,那么我们可以通过所学知识来完成一些相关的OJ问题练习,每一道题目都附上了对应的题目链接,可以先自己尝试完成,再看看这篇文章的解题思路。
1.单值二叉树
如果二叉树每个节点都具有相同的值,那么该二叉树就是单值 二叉树。只有给定的树是单值二叉树时,才返回 true;否则返回 false。
cpp
bool _isUnivalTree(struct TreeNode* root,int val)
{
if(root==NULL)
return true;
if(root->val!=val)
return false;
return _isUnivalTree(root->left,val) && _isUnivalTree(root->right,val);
}
bool isUnivalTree(struct TreeNode* root)
{
return _isUnivalTree(root,root->val);
}
我们选择创建一个辅助函数,函数参数中带上二叉树中的值,然后利用递归遍历所有节点,如果有之不相等的直接返回false。
2.相同的树
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
cpp
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);
}
首先如果两个根节点都是NULL,那么直接返回true,那么后面只要有一个节点为空,就说明另一个根节点不为空,两个肯定是不相等的,然后再利用递归,判断左右子树的根节点是否对应相等。
3.对称二叉树
给你一个二叉树的根节点 root , 检查它是否轴对称。
cpp
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->right)&&isSameTree(p->right,q->left);
}
bool isSymmetric(struct TreeNode* root)
{
return isSameTree(root->left,root->right);
}
我们很容易想到,就是证明根节点的左右子树相等,那我们直接利用上一题的函数,就可以完成了。
4. 二叉树的遍历
4.1 二叉树的前序遍历
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
cpp
int TreeSize(struct TreeNode* root)
{
return root==NULL?0:1+TreeSize(root->left)+TreeSize(root->right);
}
void PrevOrder(struct TreeNode* root,int* arr,int* pi)
{
if(root==NULL)
return;
arr[(*pi)++]=root->val;
PrevOrder(root->left,arr,pi);
PrevOrder(root->right,arr,pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
*returnSize=TreeSize(root);
int* arr=(int*)malloc(sizeof(int)*(*returnSize));
int i=0;//这里的i用来作为数组的下标
PrevOrder(root,arr,&i);
return arr;
}
在这里有两个注意点:
1.在题目的原函数中,有一个参数returnSize,这是一个指向整型变量的指针,我们需要在函数中将二叉树的节点数传给它,那么在main函数中也可以得到这个大小,这样可以方便数组的输出
2.在进行先序遍历时,我们需要一个参数i,对数组进行定位,让数据进行插入,这里使用址传递的意义是为了防止因为函数递归,在不同栈帧中,i的值不会与其他栈帧的i进行传递,那么导致i的值没有得到有效的增加,所以我们进行传址调用,对 i 解引用后再操作。
4.2中序遍历
cpp
int TreeSize(struct TreeNode* root)
{
return root==NULL?0:1+TreeSize(root->left)+TreeSize(root->right);
}
void InOrder(struct TreeNode* root,int* arr,int* pi)
{
if(root==NULL)
return;
InOrder(root->left,arr,pi);
arr[(*pi)++]=root->val;
InOrder(root->right,arr,pi);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize)
{
*returnSize=TreeSize(root);
int* arr=(int*)malloc(sizeof(int)*(*returnSize));
int i=0;//这里的i用来作为数组的下标
InOrder(root,arr,&i);
return arr;
}
这里没什么变化,就是先遍历左子树的节点,只要把顺序改变一下就行了。
4.3 后序遍历
这里不做解释了,和上面思路一致,所以只留下题目链接,代码就不留了。
5. 翻转二叉树
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
cpp
typedef struct TreeNode Tnode;
struct TreeNode* invertTree(struct TreeNode* root)
{
if(root==NULL)
return NULL;
Tnode* cyroot=(Tnode*)malloc(sizeof(Tnode));
cyroot->val=root->val;
cyroot->left=invertTree(root->right);
cyroot->right=invertTree(root->left);
return cyroot;
}
这种问题,我的常用思路就是再创建一个新的二叉树,让它的左节点接收原树的右节点,它的右节点接收原树的左节点。因为本题并没有限制空间复杂度,所以是可行的,这种方法对很多类似的题目都是有效且易于理解的,但前提是没有空间复杂度的限制。
6. 平衡二叉树
给定一个二叉树,判断它是否是 平衡二叉树
cpp
typedef struct TreeNode Tnode;
int TreeHight(Tnode* root)
{
if(root==NULL)
return 0;
int ret1=TreeHight(root->left);
int ret2=TreeHight(root->right);
return ret1>ret2?ret1+1:ret2+1;
}
bool isBalanced(struct TreeNode* root)
{
if(root==NULL)
return true;
int h1=TreeHight(root->left);
int h2=TreeHight(root->right);
if(abs(h1-h2)>1)
return false;
return isBalanced(root->left)&&isBalanced(root->right);
}
先写一个计算树的高度的函数,因为平衡二叉树需要该树所有节点的左右子树的高度相差不超过 1,那我们用两个整型变量来统计左右子树的高度,然后用绝对值函数来计算高度差,如果大于1,那么就不是平衡二叉树,如果是,那么还需要进行下一轮的比较。
结语
以上就是本篇文章的全部内容,那你是否已经熟练使用了函数的递归来解决二叉树的相关问题?后续我们将要开始排序的学习,感谢观看!