鉴于二叉树的子树及二叉树的子结构问题,现总结如下:
什么是二叉树的子结构及子树?
子树的意思是包含了一个结点,就得包含这个结点下的所有节点,一棵大小为n的二叉树有n个子树,就是分别以每个结点为根的子树。子结构的意思是包含了一个结点,可以只取左子树或者右子树,或者都不取。
1、输入两棵二叉排序树A,B,判断B是不是A的子树。(ps:我们约定空树不是任意一个树的子树)
二叉排序树,又称为二叉查找树,它或是一棵空树,或是一棵具有以下性质的树:
1)若它的左子树不空,则左子树上所有结点的值都小于它的根结点的值;
2)若它的右子树不空,则右子树上所有结点的值都小于它的根结点的值;
3)它的左右子树也分别为二叉排序树。
分析:其一、A、B是二叉搜索树,说明树中每个结点的值都大于左孩子结点的值,并且小于右孩子结点的值。
其二、判断是不是子树,说明在树A中找到和树B的根结点对应的结点后,该结点下面所有的结点都应该是一致的。
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
bool IsSametree(TreeNode* pRoot1,TreeNode* pRoot2)
{
if(pRoot1==NULL&&pRoot2 == NULL)//同时达到叶子结点
return true;
else
return false;
if(pRoot1->val == pRoot2->val)
return IsSametree(pRoot1->left,pRoot2->left)&&IsSametree(pRoot1->right,pRoot2->right);
else
return false;
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot2 == NULL)
return false;
else if(pRoot1 == NULL)
return false;
if(pRoot1->val == pRoot2->val)
return IsSametree(pRoot1,pRoot2);
if(pRoot1->val > pRoot2->val)
return HasSubtree(pRoot1->left,pRoot2);
if(pRoot1->val < pRoot2->val)
return HasSubtree(pRoot1->right,pRoot2);
}
调用的函数为HasSubtree,由于A、B为二叉排序树,所以可以根据值来判断下一步是从A的左子树还是右子树来寻找,如果没有知识单纯的二叉树,可以将值判断的两行代码用或的关系语句代替,详见下面代码。
2、剑指offer中的题目描述:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
首先仔细看题目,其一、普通的二叉树,没有别的功能;其二、子结构,可以是A树的任意一部分。
分析可能性,还是依照上面的思路来写代码,但是要有一些改变。首先,递归返回的条件不一样,当B到达了叶子结点,但是A没有到叶子结点,也是正确的,这是和上题不一样的地方。但是如果A先到叶子结点,就肯定不对,返回false。再者,因为不是二叉排序树,所以结点的值没有限制,如果不同的结点有相同的值,这就要注意了!可能找到和B根结点一样的值,但是从该结点往下查看,发现结点没有对应,不要直接返回false!因为可能有别的结点有相同的值,从该结点往下和B一样!此时要设置一个标志位,当是子结构是返回true,当不是子结构时返回false,此时再去搜索A的下一个结点,继续判断。
class Solution {
public:
bool IsSubtree(TreeNode* pRoot1,TreeNode* pRoot2)
{
if(pRoot2==NULL) //B同时或先到达叶子结点
return true;
else if(pRoot1 == NULL)
return false; //B不是空,但A是空,说明A先到达叶子结点
if(pRoot1->val == pRoot2->val)
return IsSubtree(pRoot1->left,pRoot2->left)&&IsSubtree(pRoot1->right,pRoot2->right);
else
return false;
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot2 == NULL)
return false;
else if(pRoot1 == NULL)
return false; // A先到达叶子结点
bool flag = false;
if(pRoot1->val == pRoot2->val)
flag = IsSubtree(pRoot1,pRoot2);
if(!flag)
flag = HasSubtree(pRoot1->left,pRoot2)||HasSubtree(pRoot1->right,pRoot2);
return flag;
}
};