判断二叉树B是否为二叉树B的子结构算法

问题表述
  • 输入两棵二叉树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); //进行遍历搜索
}

猜你喜欢

转载自blog.csdn.net/Leader_wang/article/details/83240686
今日推荐