您的位置:首页 > Web前端

剑指offer 18 - 树的子结构

2015-06-01 19:19 309 查看
要查找树A中是否存在和树B结构一样的子树,可以分成两步:
第一步在树A中找到和B的根节点的值一样的结点R;
第二步再判断树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.
4000
\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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: