题目来自剑指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##