每日一题(33) - 树的子结构

题目来自剑指offer

题目:


举例:


思路:

以先序的顺序对树进行处理,先比较子树的根值是否匹配,之后再比较其两个子树是否匹配

其实,这个方法类似字符串匹配的朴素方法,其实也可以先序遍历两个树,得到其先序遍历的序列,之后采用KMP算法匹配。

代码:

#include <iostream>
#include <assert.h>
using namespace std;

struct BinaryTreeNode
{
	char m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

/*
出口:
(1)模式树的根可以为空,表示某条路径上结点已经匹配结束,告诉上一层其孩子匹配
(2)模式树不为空,而主树为空时,表示不匹配
(3)模式树和主树都不为空,且其结点值有不同,直接返回不匹配
入口:
(4)模式树和主树都不为空,且其结点值都相同,继续匹配左右子树
返回值:
由于需要同时考虑左右子树,则在返回时需要同时左右子树返回的结果进行处理

*/
bool IsInclude(BinaryTreeNode* pRootTarget,BinaryTreeNode* pRootPattern)
{
	if (NULL == pRootPattern)//模式树为空,匹配成功
	{
		return true;
	}
	if (NULL == pRootTarget)//模式树不为空,主树为空,不匹配
	{
		return false;
	}
	if (pRootTarget->m_nValue != pRootPattern->m_nValue)
	{
		return false;
	}
	return IsInclude(pRootTarget->m_pLeft,pRootPattern->m_pLeft) 
		&& IsInclude(pRootTarget->m_pRight,pRootPattern->m_pRight); 
}

bool HasSubtree(BinaryTreeNode* pRootTarget,BinaryTreeNode* pRootPattern)
{
	bool bIsInclude = false;
	//边界条件
	if (NULL == pRootTarget || NULL == pRootPattern)//表示结点为NULL,表示某条路径遍历结束,均不匹配。
	{
		return false;
	}
	//判断根节点
	if (pRootTarget->m_nValue == pRootPattern->m_nValue)
	{
		bIsInclude =  IsInclude(pRootTarget,pRootPattern);
	}
	//判断左右子树是否匹配,但是在父亲已经匹配时,不用继续比较了
	if (!bIsInclude)
	{
		bIsInclude =  HasSubtree(pRootTarget->m_pLeft,pRootPattern);
	}
	if (!bIsInclude)
	{
		bIsInclude =  HasSubtree(pRootTarget->m_pRight,pRootPattern);
	}
	return bIsInclude;
}

void Create(BinaryTreeNode*& pRoot)  
{  
	char newData;  
	cin >> newData;  
	if ('#' == newData)  
	{  
		pRoot = NULL;  
	}  
	else  
	{  
		pRoot = new BinaryTreeNode;  
		pRoot->m_nValue = newData;  
		Create(pRoot->m_pLeft);  
		Create(pRoot->m_pRight);   
	}  
}  

void PreOrder(BinaryTreeNode* pRoot)
{
	if (pRoot)
	{
		cout<<pRoot->m_nValue<<" ";
		PreOrder(pRoot->m_pLeft);
		PreOrder(pRoot->m_pRight);
	}

}

int main()
{
	BinaryTreeNode* pRootTarget = NULL;
	BinaryTreeNode* pRootPattern = NULL;
	
	cout<<"Input First Tree A:"<<endl;
	Create(pRootTarget);//输入889##24##7##7##
	PreOrder(pRootTarget);
	cout<<endl;

	cout<<"Input First Tree B:"<<endl;
	Create(pRootPattern);//输入89##2##
	PreOrder(pRootPattern);
	cout<<endl;


	if (HasSubtree(pRootTarget,pRootPattern))
	{
		cout<<"树A包含树B!"<<endl;
	}
	else
	{
		cout<<"树A不包含树B!"<<endl;
	}

	system("pause");
	return 1;
}
注意:

上述代码使用先序建树,#表示结点没孩子了。

对于下图:


左边的子树输入的序列:输入889##24##7##7##

右边的子树输入的序列:输入89##2##

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值