一、相同的树
两棵树是否相同,有三种情况。1、两棵树都为空 2、两棵树有一颗为空 3、两棵树都不为空
1情况下相同,2情况下不相同,3情况下需要进一步讨论
3情况下,比较根节点的值,不相同返回false,相同则递归调用isSameTree检验左右子树。
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);
}
二、二叉树的前序遍历
这个题看上去很简单,但是要做的准备工作很多。
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
}
首先观察题目给的函数参数中, int* returnSize 其实是向我们要输出节点数。而这个题目没有给出具体的二叉树,我们不知道有多少个节点,所以写一个函数求二叉树节点个数。
int BTreeSize(struct TreeNode* root)
{
return root == NULL ? 0 : BTreeSize(root->left) + BTreeSize(root->right) + 1;
}
其次,给定函数的参数显然不适宜递归使用,所以另外创建一个函数,用递归的方法前序遍历
void _preorder(struct TreeNode* root,int* a,int* p)
{
if(root == NULL)
{
return;
}
a[(*p)++] = root->val;
_preorder(root->left,a,p);
_preorder(root->right,a,p);
}
需要注意的是,给定函数最后需要返回一个指针,所以malloc一个数组用于存储二叉树节点值;
为了按照我们的需求访问下标,这里一定采用传值调用,否则会带来很多麻烦。
最后的代码
int BTreeSize(struct TreeNode* root)
{
return root == NULL ? 0 : BTreeSize(root->left) + BTreeSize(root->right) + 1;
}
void _preorder(struct TreeNode* root,int* a,int* p)
{
if(root == NULL)
{
return;
}
a[(*p)++] = root->val;
_preorder(root->left,a,p);
_preorder(root->right,a,p);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = BTreeSize(root);
int* a = (int*)malloc(sizeof(int) * (*returnSize));
int i = 0;
_preorder(root,a,&i);
return a;
}
三、翻转二叉树
后序递归遍历
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;
}
四、对称二叉树
这道题只需要遍历左右子树,所以另分装一个函数,参数为左右子树。
bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
{
}
左右子树的情况分三种:1、左右子树都为空 2、左右子树有一个为空 3、左右子树都不为空
1情况下对称,2情况下不对称,3情况下还需进一步比较两个节点的值
bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
{
if(left == NULL && right == NULL)
return true;
if(left == NULL || right == NULL)
return false;
if(left->val != right->val)
return false;
return _isSymmetric(left->left,right->right) && _isSymmetric(left->right,right->left);
}
最后的代码
bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
{
if(left == NULL && right == NULL)
return true;
if(left == NULL || right == NULL)
return false;
if(left->val != right->val)
return false;
return _isSymmetric(left->left,right->right) && _isSymmetric(left->right,right->left);
}
bool isSymmetric(struct TreeNode* root) {
return _isSymmetric(root->left,root->right);
}
五、另一颗树的子树
root任何一个非空子树都有可能,所以遍历root所有子树,与subroot进行比较,自己也是自己的子树。
同时注意给出的范围,不需要考虑空节点。
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
if(root == NULL)
return false;
if(isSameTree(root,subRoot))
return true;
return isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
}
这里会用到之前判断树是否相同的函数
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);
}
六、平衡二叉树
平衡二叉树:所有节点的左右子树的深度相差不超过1.
首先分装一个求深度的函数
int BTreeHeight(struct TreeNode* root)
{
if(root == NULL)
return 0;
int leftheight = BTreeHeight(root->left);
int rightheight = BTreeHeight(root->right);
return leftheight > rightheight ? leftheight + 1 : rightheight + 1;
}
相当于一个前序遍历,递归求得结果
bool isBalanced(struct TreeNode* root) {
if(root == NULL)
return true;
if(abs(BTreeHeight(root->left) - BTreeHeight(root->right)) > 1)
return false;
return isBalanced(root->left) && isBalanced(root->right);
}