树的子结构

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

struct TreeNode

{

        int m_nValue;

        TreeNode* m_pLeft;

        TreeNode* m_pRight;

};

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

例如,下图中的两棵树AB,由于A中有一部分子树的结构和B是一样的,因此B就是A的子结构。

 

                 1                                                   8
               /    \                                                  \
              8                                                9    2
               \
           9    2
                /  \
               4  7

思路:先判断根节点是否同,同比较左右节点。不同,比较A左节点和B根节点,直到选出一个相同的,然后分别比较各自的子节点,都相同才是子结构

设置两个函数,一个是判断B根节点在不在A中,在的话,调用函数,判断B树是不是A树的子结构,




#include<iostream>
using namespace std;

//定义树的节点
struct BinaryTreeNode{
	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

//建立树的节点
BinaryTreeNode* CreateBinaryTreeNode(int value)
{
	BinaryTreeNode* pNode = new BinaryTreeNode();
	pNode->m_nValue = value;
	pNode->m_pLeft = NULL;
	pNode->m_pRight = NULL;

	return pNode;
}

//链接树的节点
void ConnectTreeNodes(BinaryTreeNode* pParent,BinaryTreeNode* pLeft,BinaryTreeNode* pRight)
{
	if(pParent != NULL)
	{
		pParent->m_pLeft = pLeft;
		pParent->m_pRight = pRight;
	}
}

//打印树节点
void PrintTreeNode(BinaryTreeNode* pNode)
{
	if(pNode != NULL)
	{
		cout << "节点值为:" << pNode->m_nValue << endl;
		if(pNode->m_pLeft != NULL)
			cout << "节点左孩子值为:" << pNode->m_pLeft->m_nValue << endl;
		else
			cout << "节点没有左孩子值为:" << endl;

		if(pNode->m_pRight != NULL)
			cout << "节点左孩子值为:" << pNode->m_pRight->m_nValue << endl;
		else
			cout << "节点没有左孩子值为:" << endl;
	}
	else
			cout << "该节点为空节点"  << endl;
}

//打印树
void PrintTree(BinaryTreeNode* pRoot)
{
	PrintTreeNode(pRoot);
	if(pRoot->m_pLeft != NULL)
		PrintTreeNode(pRoot->m_pLeft);
	if(pRoot->m_pRight != NULL)
		PrintTreeNode(pRoot->m_pRight);
}

//摧毁二叉树
void DestroyTree(BinaryTreeNode* pRoot)
{
	if(pRoot != NULL)
	{
		BinaryTreeNode* pLeft = pRoot->m_pLeft;
		BinaryTreeNode* pRight = pRoot->m_pRight;

		delete pRoot;
		pRoot = NULL;
		DestroyTree(pLeft);
		DestroyTree(pRight);
	
	}

}

//查看是不是子结构

bool HasSubtree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2);//在A中找到和B根节点一样的点
bool DoesTree1HasTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2);

bool HasSubTree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
	bool result = false;
	if(pRoot1 != NULL && pRoot2 != NULL)
	{
		if(pRoot1->m_nValue = pRoot2->m_nValue)//如果根节点相同,继续遍历左右节点
			result = DoesTree1HasTree2(pRoot1, pRoot2);
		if(!result)//如果左右节点不相同,则比较左节点和2的根节点
			result = HasSubTree(pRoot1->m_pLeft,pRoot2);
		if(!result)
			result = HasSubTree(pRoot1->m_pRight,pRoot2);	
	}
	return result;
}
bool DoesTree1HasTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
	if(pRoot2 == NULL)
		return true;
	if(pRoot1 == NULL)
		return false;
	if(pRoot1->m_nValue != pRoot2->m_nValue)
		return false;

	return DoesTree1HasTree2(pRoot1->m_pLeft,pRoot2->m_pLeft)&&DoesTree1HasTree2(pRoot1->m_pRight,pRoot2->m_pRight);
}


// 树中结点含有分叉,树B是树A的子结构
//                  8                8
//              /       \           / \
//             8         7         9   2
//           /   \
//          9     2
//               / \
//              4   7

int _tmain(int argc, _TCHAR* argv[])
{
	BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode(7);
    BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode(9);
    BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode(2);
    BinaryTreeNode* pNodeA6 = CreateBinaryTreeNode(4);
    BinaryTreeNode* pNodeA7 = CreateBinaryTreeNode(7);

	ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3);
    ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5);
    ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7);

    BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode(9);
    BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode(2);

    ConnectTreeNodes(pNodeB1, pNodeB2, pNodeB3);
	cout << HasSubTree(pNodeA1, pNodeB1) << endl;;
	 DestroyTree(pNodeA1);
    DestroyTree(pNodeB1);
	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值