题目:二叉树的结点定义如下:
struct TreeNode
{
int m_nValue;
TreeNode* m_pLeft;
TreeNode* m_pRight;
};
输入两棵二叉树A和B,判断树B是不是A的子结构。
例如,下图中的两棵树A和B,由于A中有一部分子树的结构和B是一样的,因此B就是A的子结构。
1 8
/ \/ \
87 9 2
/ \
9 2
/ \
47
分析:这是2010年微软校园招聘时的一道题目。二叉树一直是微软面试题中经常出现的数据结构。对微软有兴趣的读者一定要重点关注二叉树。
回到这个题目的本身。要查找树A中是否存在和树B结构一样的子树,我们可以分为两步:第一步在树A中找到和B的根结点的值一样的结点N,第二步再判断树A中以N为根结点的子树是不是包括和树B一样的结构。
第一步在树A中查找与根结点的值一样的结点。这实际上就是树的遍历。对二叉树这种数据结构熟悉的读者自然知道我们可以用递归的方法去遍历,也可以用循环的方法去遍历。由于递归的代码实现比较简洁,面试时如果没有特别要求,我们通常都会采用递归的方式。下面是参考代码:
// SubTree1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
typedef struct Tree
{
int m_nValue;
struct Tree* m_pLeft;
struct Tree* m_pRight;
}TreeNode;
TreeNode* createTree()
{
int x;
cin>>x;
TreeNode* temp;
if(x==-1)
temp =NULL;
else
{
temp = new TreeNode();
temp->m_nValue=x;
temp->m_pLeft=createTree();
temp->m_pRight =createTree();
}
return temp;
}
bool DoesTree1HaveAllNodesOfTree2(TreeNode* pTreeHead1, TreeNode* pTreeHead2)
{
if(pTreeHead2 == NULL)
return true;
if(pTreeHead1 == NULL)
return false;
if(pTreeHead1->m_nValue != pTreeHead2->m_nValue)
return false;
return DoesTree1HaveAllNodesOfTree2(pTreeHead1->m_pLeft, pTreeHead2->m_pLeft) &&
DoesTree1HaveAllNodesOfTree2(pTreeHead1->m_pRight, pTreeHead2->m_pRight);
}
bool HasSubtreeCore(TreeNode* pTreeHead1, TreeNode* pTreeHead2)
{
bool result = false;
if(pTreeHead1->m_nValue == pTreeHead2->m_nValue)
{
//只要有一个相同的节点那么就可以开始
result = DoesTree1HaveAllNodesOfTree2(pTreeHead1, pTreeHead2);
}
if(!result && pTreeHead1->m_pLeft != NULL)
result = HasSubtreeCore(pTreeHead1->m_pLeft, pTreeHead2);
if(!result && pTreeHead1->m_pRight != NULL)
result = HasSubtreeCore(pTreeHead1->m_pRight, pTreeHead2);
return result;
}
bool HasSubtree(TreeNode* pTreeHead1, TreeNode* pTreeHead2)
{
if((pTreeHead1 == NULL && pTreeHead2 != NULL) ||(pTreeHead1 != NULL && pTreeHead2 == NULL))
return false;
if(pTreeHead1 == NULL && pTreeHead2 == NULL)
return true;
return HasSubtreeCore(pTreeHead1, pTreeHead2);
}
int _tmain(int argc, _TCHAR* argv[])
{
cout<<"请输入第一颗树"<<endl;
TreeNode* root1= createTree();
cout<<"请输入第二颗树"<<endl;
TreeNode* root2= createTree();
cout<<HasSubtree(root1,root2);
system("pause");
return 0;
}
或者代码如下:
// SubTree1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#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 x;
cin>>x;
TreeNode* temp;
if(x==-1)
temp =NULL;
else
{
temp = new TreeNode();
temp->m_nValue=x;
temp->m_pLeft=createTree();
temp->m_pRight =createTree();
}
return temp;
}
TreeNode* createTree2(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=createTree2(a);
temp->m_pRight =createTree2(a);
}
return temp;
}
bool DoesTree1HaveAllNodesOfTree2(TreeNode* pTreeHead1, TreeNode* pTreeHead2)
{
if(pTreeHead2 == NULL)
return true;
if(pTreeHead1 == NULL)
return false;
if(pTreeHead1->m_nValue != pTreeHead2->m_nValue)
return false;
return DoesTree1HaveAllNodesOfTree2(pTreeHead1->m_pLeft, pTreeHead2->m_pLeft) &&
DoesTree1HaveAllNodesOfTree2(pTreeHead1->m_pRight, pTreeHead2->m_pRight);
}
bool HasSubtreeCore(TreeNode* pTreeHead1, TreeNode* pTreeHead2)
{
bool result = false;
if(pTreeHead1->m_nValue == pTreeHead2->m_nValue)
{
//只要有一个相同的节点那么就可以开始
result = DoesTree1HaveAllNodesOfTree2(pTreeHead1, pTreeHead2);
}
if(!result && pTreeHead1->m_pLeft != NULL)
result = HasSubtreeCore(pTreeHead1->m_pLeft, pTreeHead2);
if(!result && pTreeHead1->m_pRight != NULL)
result = HasSubtreeCore(pTreeHead1->m_pRight, pTreeHead2);
return result;
}
bool HasSubtree(TreeNode* pTreeHead1, TreeNode* pTreeHead2)
{
if((pTreeHead1 == NULL && pTreeHead2 != NULL) ||(pTreeHead1 != NULL && pTreeHead2 == NULL))
return false;
if(pTreeHead1 == NULL && pTreeHead2 == NULL)
return true;
return HasSubtreeCore(pTreeHead1, pTreeHead2);
}
int _tmain(int argc, _TCHAR* argv[])
{
//cout<<"请输入第一颗树"<<endl;
//TreeNode* root1= createTree();
int nodesA[] = {1, 8, 9, -1, -1, 2, 4, -1, -1, 7, -1, -1, 7, -1, -1};
int nodesB[] = {8, 9, -1, -1, 2, -1, -1};
TreeNode* root1= createTree2(nodesA);
TreeNode* root2= createTree2(nodesB);
//cout<<"请输入第二颗树"<<endl;
//TreeNode* root2= createTree();
cout<<HasSubtree(root1,root2);
system("pause");
return 0;
}