版权声明:本文为博主原创学习笔记,如需转载请注明来源。 https://blog.csdn.net/SHU15121856/article/details/82460737
面试题26:二叉树的子结构
输入两棵二叉树A和B,判断B是不是A的子结构。树的结点里存的是double类型的值。
如果树A根和树B根相同,只要判断树B是不是树A的残疾子树,这个可以单独拿到一个递归函数里。如果不相同,再递归地调用解决问题的函数,判断树A的左子树和树A的右子树。
在外层的这个递归函数里,树B是不用取子的,一直往里传,只要判断出了true就不需要树A其它位置的判断了,一直网上返回true就可以了。
在判断残疾子树的函数里,根结点判断完,要分别判断A和B这两棵树的左右子树,这时需要考虑好递归的出口。
我把作者对这道题写的二叉树单独拿到另外的文件里了,二叉树的实现和之前的基本一样不再贴了。
#include<bits/stdc++.h>
#include "../Utilities/DblBinaryTree.h"
using namespace std;
bool DoesTree1HaveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2);
bool Equal(double num1, double num2);
//递归函数,传入两个二叉树(树根),判断第二个是否是第一个的子结构
bool HasSubtree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2) {
bool result = false;
//两棵树根都不为空时才做判断
if(pRoot1 != nullptr && pRoot2 != nullptr) {
if(Equal(pRoot1->m_dbValue, pRoot2->m_dbValue))//如果树根相同
result = DoesTree1HaveTree2(pRoot1, pRoot2);//从该位置开始判断是不是残疾子树
if(!result)//如果上一步判断完仍然是false
result = HasSubtree(pRoot1->m_pLeft, pRoot2);//从第1棵树的左子树上调用自身再判断
if(!result)//如果上一步判断完仍然是false
result = HasSubtree(pRoot1->m_pRight, pRoot2);//从第1棵树的右子树上调用自身再判断
}
return result;
}
//递归函数,传入两个二叉树(树根),判断第二个是否是第一个的残疾情况
//即第二个是否是第一个去掉一些非根结点,或者去掉全部结点(nullptr)的情况
bool DoesTree1HaveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2) {
if(pRoot2 == nullptr)//如果第二个为空
return true;//相当于第一个去掉了所有结点
if(pRoot1 == nullptr)//如果第二个不为空(执行至此),且第一个为空
return false;//那么第一个怎么去掉都不对
//至此,两棵树都不为空,要做递归判断
if(!Equal(pRoot1->m_dbValue, pRoot2->m_dbValue))//如果两棵树的根节点都不相等
return false;//那么也是从第1棵树里怎么去掉都不对
//递归地判断左右子树是否也分别是第1棵树的左右子树的残疾情况
return DoesTree1HaveTree2(pRoot1->m_pLeft, pRoot2->m_pLeft) &&
DoesTree1HaveTree2(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;
}
// 树中结点含有分叉,树B是树A的子结构
// 8 8
// / \ / \
// 8 7 9 2
// / \
// 9 2
// / \
// 4 7
bool test1() {
BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode(7);
BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode(9);
BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode(2);
BinaryTreeNode* pNodeA6 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNodeA7 = CreateBinaryTreeNode(7);
ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3);
ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5);
ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7);
BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode(9);
BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode(2);
ConnectTreeNodes(pNodeB1, pNodeB2, pNodeB3);
return HasSubtree(pNodeA1,pNodeB1);
}
// 树中结点含有分叉,树B不是树A的子结构
// 8 8
// / \ / \
// 8 7 9 2
// / \
// 9 3
// / \
// 4 7
bool test2() {
BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode(7);
BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode(9);
BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode(3);
BinaryTreeNode* pNodeA6 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNodeA7 = CreateBinaryTreeNode(7);
ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3);
ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5);
ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7);
BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode(9);
BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode(2);
ConnectTreeNodes(pNodeB1, pNodeB2, pNodeB3);
return HasSubtree(pNodeA1,pNodeB1);
}
int main() {
cout<<boolalpha<<test1()<<endl;
cout<<boolalpha<<test2()<<endl;
return 0;
}
至此,《剑指Offer》第三章就读完了。