前言
关于普通二叉树的递归写法,写起来简单,理解起来是有点困难的,需要有前序、中序、后序遍历的基础。本章题解不画递归展开图,仅提供思考和代码。
一、本章重点
- .单值二叉树
- 检查两颗树是否相同
- 对称二叉树
- 另一颗树的子树
- 二叉树的构建及遍历
二、单值二叉树
bool isUnivalTree(struct TreeNode* root)
递归思路:当根为NULL时,返回true。
当左孩子存在时,如果左孩子的值不等于根节点的值,返回false。
同理当右孩子存在时,如果右孩子的值不等于根节点的值,返回false。
接下来要满足:
return isUnivalTree(root->left) && isUnivalTree(root->right);
参考代码:
bool isUnivalTree(struct TreeNode* root) { if(root==NULL) { return true; } if(root->right && root->val!=root->right->val) { return false; } if(root->left && root->val!=root->left->val) { return false; } //以上三个if为递归的出口 return isUnivalTree(root->left) && isUnivalTree(root->right);//分治,安排任务下去 }
如果感觉写完有点难以置信的感觉,那需要画递归展开图,也开在脑海中执行递归的步骤。
初次写递归还是画图理解较好。
三、检查两颗树是否相同
bool isSameTree(struct TreeNode* p, struct TreeNode* q)
递归思路:
当p为空,q为空时,返回true
当p和q其中有一个为空,另一个不为空,返回false。
当p->val!=q->val,返回true。
最后:
return isSameTree(p->left,q->left) &&isSameTree(p->right,q->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 isSymmetric(struct TreeNode* root)
递归思路:如果根为NULL,返回true。
在判断左子树与右子树这两棵树是对称关系,这里的函数原型只包含一个根,显然不行,这里我们重写一个子函数:
bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
如果left和right都等于NULL,说明两个树对称。
如果一个为空,另一个不为空,说明不对称。
两个都不为空的话:如果left->val!=right->val,返回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) { if(root==NULL) { return true; } return _isSymmetric(root->left,root->right); }
五、另一颗树的子树
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
题目说明:自身可看做自身的子树
递归写法:
要判断是否为子树,从自身开始,借助上面题三判断两棵树是否相同的代码。
如果:
if(isSameTree(root,subRoot)) { return true; }
再判断:
return isSubtree(root->right,subRoot) ||isSubtree(root->left,subRoot);
但不要忘记写上root==NULL,否则root->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(isSameTree(root,subRoot)) { return true; } if(root==NULL) { return false; } return isSubtree(root->right,subRoot) ||isSubtree(root->left,subRoot); }
六、 二叉树遍历
这是牛客的一道题,是io型的题。
输入:
char string[100]; scanf("%s",string);
第一件事:将字符串建链式二叉树,由于是前序的字符串,用前序遍历接收即可。
参考代码:
TreeNode* CreatBinaryTree(char* s,int* i) { if(s[*i]=='#') { (*i)++; return NULL; } TreeNode* root=(TreeNode*)malloc(sizeof(TreeNode)); root->val=s[*i]; (*i)++; root->left=CreatBinaryTree(s,i); root->right=CreatBinaryTree(s,i); return root; }
建完二叉树用中序遍历即可。
参考代码:
void PrevOrder(TreeNode* root) { if(root==NULL) { return; } PrevOrder(root->left); printf("%c ",root->val); PrevOrder(root->right); }