程序员面试题精选100题(50)-树的子结构
题目:二叉树的结点定义如下:
struct TreeNode
{
int m_nValue;
TreeNode* m_pLeft;
TreeNode* m_pRight;
};
输入两棵二叉树A和B,判断树B是不是A的子结构。
例如,下图中的两棵树A和B,由于A中有一部分子树的结构和B是一样的,因此B就是A的子结构。
1 8
/ \ / \
8 7 9 2
/ \
9 2
/ \
4 7
分析:这是2010年微软校园招聘时的一道题目。二叉树一直是微软面试题中经常出现的数据结构。对微软有兴趣的读者一定要重点关注二叉树。
回到这个题目的本身。要查找树A中是否存在和树B结构一样的子树,我们可以分为两步:第一步在树A中找到和B的根结点的值一样的结点N,第二步再判断树A中以N为根结点的子树是不是包括和树B一样的结构。
第一步在树A中查找与根结点的值一样的结点。这实际上就是树的遍历。对二叉树这种数据结构熟悉的读者自然知道我们可以用递归的方法去遍历,也可以用循环的方法去遍历。由于递归的代码实现比较简洁,面试时如果没有特别要求,我们通常都会采用递归的方式。
具体测试代码如下:
#include<iostream>
using namespace std;
typedef struct Tree
{
int m_nValue;
struct Tree* m_pLeft;
struct Tree* m_pRight;
}TreeNode;
int pos=0;
TreeNode* createTree(int a[])
{
int x;
x=a[pos++];
TreeNode* temp;
if(x==-1)
temp=NULL;
else
{
temp=new TreeNode();
temp->m_nValue=x;
temp->m_pLeft=createTree(a);
temp->m_pRight=createTree(a);
}
return temp;
}
bool DoesTree1HaveTree2(TreeNode* pTreeHead1,TreeNode* pTreeHead2)
{
if(pTreeHead2==NULL)
return true;
if(pTreeHead1==NULL)
return false;
if(pTreeHead1->m_nValue!=pTreeHead2->m_nValue)
return false;
return DoesTree1HaveTree2(pTreeHead1->m_pLeft,pTreeHead2->m_pLeft) &&DoesTree1HaveTree2(pTreeHead1->m_pRight,pTreeHead2->m_pRight);
}
bool HasSubtree(TreeNode* pTreeHead1,TreeNode* pTreeHead2)
{
bool result=false;
if(pTreeHead1!=NULL && pTreeHead2!=NULL)
{
if(pTreeHead1->m_nValue==pTreeHead2->m_nValue)
result=DoesTree1HaveTree2(pTreeHead1,pTreeHead2);
if(!result)
result=HasSubtree(pTreeHead1->m_pLeft,pTreeHead2);
if(!result)
result=HasSubtree(pTreeHead1->m_pRight,pTreeHead2);
}
return result;
}
int main(int argc,char* argv[])
{
int nodeA[]={1,8,9,-1,-1,2,4,-1,-1,7,-1,-1,7,-1,-1};
int nodeB[]={8,9,-1,-1,2,-1,-1};
TreeNode* root1=createTree(nodeA);
TreeNode* root2=createTree(nodeB);
cout<<HasSubtree(root1,root2);
system("pause");
}