树的子结构
1、题目
输入两颗二叉树A和B,判断B是不是A的子结构。二叉树节点的定义如下:
struct BinaryTreeNode
{
double m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
输入参数:二叉树根节点1,二叉树根节点2
输出结果:true 或 false
2、解题
此题的关键主要在于两个递归
- 第一个递归是找到树A第一个和树B的根节点值一样的节点R
- 第二个递归是找到节点R后与树B剩余节点的比较
此题可分为两个步骤
- 在树A中查找与根节点值一样的节点R,即树的遍历,用递归实现即可
- 判断树A中以R为根节点的子树和树B是否有相同结构,同样可以用递归实现
3、完整代码
bool HasSubtree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2) {
bool result = false;
//必要的鲁棒性检查
if(pRoot1 != nullptr && pRoot2 != nullptr){
if (Equal(pRoot1->m_nValue, pRoot2->m_nValue))
result = DoesTree1HasTree2(pRoot1, pRoot2);
if (!result) {
result = HasSubtree(pRoot1->m_pLeft, pRoot2);
}
if (!result) {
result = HasSubtree(pRoot1->m_pRight, pRoot2);
}
}
//返回结果
return result;
}
bool DoesTree1HasTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2) {
//首先对结束条件做判断
if (pRoot2 == nullptr)
return true;
if (pRoot1 == nullptr)
return false;
//对根节点的值进行比较,若不相等,直接返回false
if (!Equal(pRoot1->m_nValue, pRoot2->m_nValue))
return false;
//否则继续对左右子树进行比较
return DoesTree1HasTree2(pRoot1->m_pLeft, pRoot2->m_pLeft) && DoesTree1HasTree2(pRoot1->m_pRight, pRoot2->m_pRight);
}
bool Equal(double num1, double num2) {
if ((num1 - num2 > -0.0000001) && (num1 - num2) < 0.0000001)
return true;
else
return false;
}
4、注意点
- 代码的鲁棒性,有多处地方需要对参数是否为空指针进行处理
- 找到根节点时,遍历的结束条件是是否到达树B的叶节点,即所有节点对比结束
- 递归的逻辑,先对根节点的值进行对比,再递归其子树,需要理清其中的逻辑
- 尽管在首次进入
DoesTree1HasTree2()
函数之前需要将已经比较的根节点的值再比较一遍,但这是必要的,否则后面的递归调用就无法比较了