剑指offer 18 - 树的子结构

要查找树A中是否存在和树B结构一样的子树,可以分成两步:

  1. 第一步在树A中找到和B的根节点的值一样的结点R;
  2. 第二步再判断树A中以R为根结点的子树是不是包含和树B一样的结构。

第一步在树A中查找与根结点的值一样的结点,这实际上就是树的遍历。递归调用HasSubTree遍历二叉树A。如果发现某一结点的值和树B的头结点的值相同,则调用DoesTreeHavaTree2,做第二步判断。

第二步是判断树A中以R为根结点的子树是不是和树B具有相同的结构。

注意在使用指针的时候一定要注意边界条件,即检查空指针。当树A或树B为空的时候,定义相应的输出。如果没有检查并做相应的处理,程序非常容易崩溃。


#include <iostream>
#include<deque>
using namespace std;

struct BinaryTreeNode
{
	int m_nValue;
	BinaryTreeNode*m_pLeft;
	BinaryTreeNode*m_pRight;
};

BinaryTreeNode* CreateBinaryTreeNode(int value)
{
	 BinaryTreeNode*head = new  BinaryTreeNode[sizeof(BinaryTreeNode )];
	 head->m_nValue = value;
	 head->m_pLeft = head->m_pRight= NULL;

	 return head;
}

void ConnectTreeNodes(BinaryTreeNode*    root ,BinaryTreeNode*   left, BinaryTreeNode*   right)    
{  
	   if(root != NULL)
	   {
	  root->m_pLeft = left;
	  root->m_pRight = right;
	   }
}   

void DestroyTree(BinaryTreeNode*    root)
{
		if(root !=NULL)
		{
			 BinaryTreeNode* left = root->m_pLeft;
			 BinaryTreeNode* right= root->m_pRight;
 
			 delete root;
			 root=NULL;
			 DestroyTree(left);
			 DestroyTree( right);
		} 
}

bool DoesTree1haveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
		if(pRoot2==NULL)       //终止条件是到达了A或B的叶子节点    这两个if 顺序也很重要
		return  true;
		if(pRoot1==NULL) 
		return false;
		if(pRoot1->m_nValue!=pRoot2->m_nValue)   //节点值不相同
		return false;
		return DoesTree1haveTree2(pRoot1->m_pLeft,pRoot2->m_pLeft) &&
		DoesTree1haveTree2(pRoot1->m_pRight,pRoot2->m_pRight);
}

bool HasSubtree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
		bool result = false;
		if(pRoot1!=NULL && pRoot2!=NULL)   //A或B为空,则返回false
		{
		if(pRoot1->m_nValue==pRoot2->m_nValue)   //第一步 查找根值相同的节点
		result = DoesTree1haveTree2(pRoot1,pRoot2);   //第二步  判断子树是否相同
		if(!result)
		result = HasSubtree(pRoot1->m_pLeft,pRoot2);
		if(!result)
		result = HasSubtree(pRoot1->m_pRight,pRoot2);
		}
		return result;
}


void Test(char* testName, BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2, bool expected)
{
    if(HasSubtree(pRoot1, pRoot2) == expected)
        printf("%s passed.\n", testName);
    else
        printf("%s failed.\n", testName);
}
//            8                   8
//         /      \             /   \  
//        8        7          9   2
//       /  \         
//      9   2
//         /  \         
//        4   7
void Test1()
{
	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);

    Test("Test1", pNodeA1, pNodeB1, true);
}

// 树中结点含有分叉,树B不是树A的子结构
//                  8                8
//              /       \           / \
//             8         7         9   2
//           /   \
//          9     3
//               / \
//              4   7
void Test2()
{
    BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode(7);
    BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode(9);
    BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode(3);
    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);
	
    Test("Test2", pNodeA1, pNodeB1, false);
	
    DestroyTree(pNodeA1);
    DestroyTree(pNodeB1);
}

// 树中结点只有左子结点,树B是树A的子结构
//                8                  8
//              /                   / 
//             8                   9   
//           /                    /
//          9                    2
//         /      
//        2        
//       /
//      5
void Test3()
{
    BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode(9);
    BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode(2);
    BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode(5);
	
    ConnectTreeNodes(pNodeA1, pNodeA2, NULL);
    ConnectTreeNodes(pNodeA2, pNodeA3, NULL);
    ConnectTreeNodes(pNodeA3, pNodeA4, NULL);
    ConnectTreeNodes(pNodeA4, pNodeA5, NULL);
	
    BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode(9);
    BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode(2);
	
    ConnectTreeNodes(pNodeB1, pNodeB2, NULL);
    ConnectTreeNodes(pNodeB2, pNodeB3, NULL);
	
    Test("Test3", pNodeA1, pNodeB1, true);
	
    DestroyTree(pNodeA1);
    DestroyTree(pNodeB1);
}

// 树A为空树
void Test4()
{
    BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode(9);
    BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode(3);
    BinaryTreeNode* pNodeB4 = CreateBinaryTreeNode(2);
	
    ConnectTreeNodes(pNodeB1, NULL, pNodeB2);
    ConnectTreeNodes(pNodeB2, pNodeB3, pNodeB4);
	
    Test("Test7", NULL, pNodeB1, false);
	
    DestroyTree(pNodeB1);
}

// 树B为空树
void Test5()
{
    BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode(8);
    BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode(9);
    BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode(3);
    BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode(2);
	
    ConnectTreeNodes(pNodeA1, NULL, pNodeA2);
    ConnectTreeNodes(pNodeA2, pNodeA3, pNodeA4);
	
    Test("Test8", pNodeA1, NULL, false);
	
    DestroyTree(pNodeA1);
}

// 树A和树B都为空
void Test6()
{
    Test("Test9", NULL, NULL, false);
}
int main()
{
	Test1();
	Test2();
	Test3();
	Test4();
	Test5();
	Test6();
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值