树的子结构[数据结构]

题目:二叉树的结点定义如下:

struct TreeNode

{

int m_nValue;

TreeNode* m_pLeft;

TreeNode* m_pRight;

};

输入两棵二叉树AB,判断树B是不是A的子结构。

例如,下图中的两棵树AB,由于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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值