问题表述
- 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
最先的思路
- 我最先想到的就是对A树进行层次遍历,寻找A树于B树根结点值相同的节点,然后以该结点为根结点建立子树,对子树和B树进行层次遍历判断B树是否为A树的子结构,直至A树遍历完毕或者B树遍历完毕。但在牛客网运行超过允许运行时间,不知道算法那里写错了还是太过于复杂。
- 非递归代码
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
list<TreeNode*> queue_tree1;
list<TreeNode*> queue_childtree1;
list<TreeNode*> queue_tree2;
queue_tree1.push_back(pRoot1);
if(!pRoot2)
return false;
while(!queue_tree1.empty())
{
TreeNode* top = queue_tree1.front();
bool isok = true;
if(top->val == pRoot2->val) //进行匹配
{
TreeNode* temp1 = top; //子树跟节点
TreeNode* temp2 = pRoot2;
queue_childtree1.push_back(temp1);
queue_tree2.push_back(temp2);
while(!queue_tree2.empty())
{
temp1=queue_childtree1.front();
temp2=queue_tree2.front();
if(temp1->val==temp2->val) //子树和B树进行比较
{
if(temp1->left&&temp2->left)
{
queue_childtree1.push_back(temp1->left);
queue_tree2.push_back(temp2->left);
}
if(temp1->right&&temp2->right)
{
queue_childtree1.push_back(temp1->right);
queue_tree2.push_back(temp2->right);
}
queue_childtree1.pop_front();
queue_tree2.pop_front();
}
else
{ //不是子结构,isok设置为false
queue_childtree1.clear();
queue_tree2.clear();
isok = false;
break;
}
}
if(isok==true)
return true
}
if(!isok) //探寻A树的下一个节点
{
if(top->left)
queue_tree1.push_back(top->left);
if(top->right)
queue_tree1.push_back(top->right);
queue_tree1.pop_front();
}
}
return false;
}
递归算法
- 这个问题适合用递归方式写出来,思路还是比较A树的每一个节点和B树的根结点,如果找到就进一步比较子树和B树的所有节点,显而易见,需要两个功能函数,一个用于子树的比较的子函数,一个用于调用子函数的主函数。
- 递归代码
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
bool dfs(TreeNode * R1,TreeNode* R2) //深度优先遍历 广度优先遍历需要链表的辅助,所以采用深度遍历
{
if(!R2) //B树遍历完毕,所有节点都包含,为子结构
return true;
if(!R1) //A树遍历完毕,但B树还没有,所以不是子结构
return false;
if(R1->val!=R2->val) //两个节点的值不相同,不能继续比较下去了
return false;
return dfs(R1->left,R2->left) && dfs(R1->right,R2->right); //对左右节点进行比较
}
bool subtree(TreeNode* pRoot1,TreeNode* pRoot2)
{
if(!pTreeNode2) //空节点不为任何树的子结构
return false;
if(!pRoot1) //A树为空还比较个毛
return false;
return (dfs(pRoot1,pRoot2))||subtree(pRoot1->left,pRoot2)||subtree(pRoot->right,pRoot2); //进行遍历搜索
}