剑指offer-第三章高质量代码(树的子结构)

题目:输入两个二叉树A和B,判断B是不是A的子结构。

思路:遍历A树找到B树的根节点,然后再判断左右子树是否相同。不相同再往下找。重复改过程。

子结构的描述如下图所示:

C++代码:

#include<iostream>
using namespace std;
struct BinaryTreeNode
{    
    int m_nValue;
    BinaryTreeNode* m_pLeft;
    BinaryTreeNode* m_pRight;
};
BinaryTreeNode* ConstructCore(int* startPreorder,int* endPreorder,int* startInorder,int* endInorder)
{
    int rootValue=startPreorder[0];
    BinaryTreeNode* root=new BinaryTreeNode();
    root->m_nValue=rootValue;
    root->m_pLeft=root->m_pRight=NULL;
    if(startPreorder==endPreorder)
    {
        if(startInorder==endInorder&&*startPreorder==*startInorder)
        {
            return root;
        }
    else
        throw std::exception("Invalid put!"); 
    }
    //通过中序遍历序列找到根节点
    int* rootInorder=startInorder;
    while(rootInorder<=endInorder&&*rootInorder!=rootValue)
    {
        ++rootInorder;
    }
    if(rootInorder==endInorder&&*rootInorder!=rootValue)
    {
        throw std::exception("Invalid put");
    }
    int leftLength=rootInorder-startInorder;
    int rightLength=endInorder-rootInorder;
    int* leftPreorderEnd=startPreorder+leftLength;
    if(leftLength>0)
    {
        //递归构建左子树
        root->m_pLeft=ConstructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);
    }
    if(rightLength>0)
    {
        //递归构建右子树
        root->m_pRight=ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
    }
    return root;
}

BinaryTreeNode* Construct(int* preorder,int* inorder,int length)
{
    if(preorder==NULL||inorder==NULL||length<=0)
    {
    throw std::exception("Invalid put!");
    }
    return ConstructCore(preorder,preorder+length-1,inorder,inorder+length-1);
}
 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);
}
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)
            result=hasSubTree(pRoot1->m_pLeft,pRoot2);
        if(!result)
            result=hasSubTree(pRoot1->m_pRight,pRoot2);
    }
    return result;
}
void PrintTreeNode(BinaryTreeNode* pNode)  

{  
    if(pNode != NULL)  
    {  
        printf("value of this node is: %d\n", pNode->m_nValue);  
        if(pNode->m_pLeft != NULL)  
            printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);  
        else 
            printf("left child is null.\n");  
        if(pNode->m_pRight != NULL)  
            printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);  
        else 
            printf("right child is null.\n");  
    }  
    else 
    {  
        printf("this node is null.\n");  
    }  
    printf("\n");  
}  
 
//递归打印左右子树
void PrintTree(BinaryTreeNode* pRoot)  
{  
    PrintTreeNode(pRoot);  
    if(pRoot != NULL)  
    {  
        if(pRoot->m_pLeft != NULL)  
            PrintTree(pRoot->m_pLeft); 
        if(pRoot->m_pRight != NULL)  
            PrintTree(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);  
    }  
}  

void main()  
{    
    const int length1 = 8;  
    const int length2 = 3;
    int preorder1[length1] = {1, 2, 4, 7, 3, 5, 6, 8}; 
    int inorder1[length1] = {4, 7, 2, 1, 5, 3, 8, 6};   
    int preorder2[length2]={3,5,6};
    int inorder2[length2]={5,3,6};
    BinaryTreeNode *root1 = Construct(preorder1, inorder1, length1);  
    BinaryTreeNode *root2 =Construct(preorder2, inorder2, length2);    
    PrintTree(root1);  
    PrintTree(root2);
    if(hasSubTree(root1,root2))    
    cout<<"hello!"<<endl;
    else
        cout<<"world!"<<endl;
}  

Java代码:

public class IsSubTree {
public static class BinaryTreeNode
{
    int m_nValue;
    BinaryTreeNode m_pLeft;
    BinaryTreeNode m_pRight;
};
public static BinaryTreeNode ConstructBiTree(int[] preOrder,int start,int[] inOrder,int end,int length)
{
    //参数验证 ,两个数组都不能为空,并且都有数据,而且数据的数目相同  
    if (preOrder == null || inOrder == null     
            || inOrder.length != preOrder.length  || length <= 0) {    
        return null;    
    }    
    int value=preOrder[start];
    BinaryTreeNode root=new BinaryTreeNode();
    root.m_nValue=value;
    root.m_pLeft=root.m_pRight=null;  
  //递归终止条件:子树只有一个节点    
    if (length == 1){  
        if(inOrder[end]==value)  
            return root;    
         else   
            throw new RuntimeException("Invalid input");  
    }                       
    //分拆子树的左子树和右子树    
    int i = 0;    
    while (i < length) {    
        if (value == inOrder[end - i]) {    
            break;    
        }    
        i++;    
    }    
    if(i==length)  
        throw new RuntimeException("Invalid input");  
    //建立子树的左子树    
    root.m_pLeft = ConstructBiTree(preOrder, start + 1, inOrder, end - i - 1, length - 1 - i);    
    //建立子树的右子树    
    root.m_pRight = ConstructBiTree(preOrder, start + length - i, inOrder, end, i );       
    return root;    
}
 public static boolean DoesTree1HasTree2(BinaryTreeNode pRoot1,BinaryTreeNode pRoot2)
{   //树A存在树B的根节点时,判断B的左右子树是否也存在A树中。
    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);
}
public static boolean  hasSubTree(BinaryTreeNode pRoot1,BinaryTreeNode pRoot2)
{   //判断是否是子树
    boolean result=false;
    if(pRoot1!=null&&pRoot2!=null)
    {
        if(pRoot1.m_nValue==pRoot2.m_nValue)
            result=DoesTree1HasTree2(pRoot1,pRoot2);//树A存在树B的根节点时,判断B的左右子树是否也存在A树中。
        if(!result)
            result=hasSubTree(pRoot1.m_pLeft,pRoot2);//在左子树中找B的根节点。
        if(!result)
            result=hasSubTree(pRoot1.m_pRight,pRoot2);//在右子树中找B的根节点。
    }
    return result;
}
public static void PrintTreeNode(BinaryTreeNode pNode)  
{  
    if(pNode !=null)  
    {  
        System.out.println("the Node is:"+pNode.m_nValue); 
         if(pNode.m_pLeft != null)  
System.out.println(
"left child is:"+pNode.m_pLeft.m_nValue); else System.out.println("left child is null.\n"); if(pNode.m_pRight != null) System.out.println("right child is:"+pNode.m_pRight.m_nValue); else System.out.println("right child is null.\n"); } else { System.out.println("this node is null.\n"); } System.out.println(); } //递归打印左右子树 public static void PrintTree(BinaryTreeNode pRoot) { PrintTreeNode(pRoot); if(pRoot !=null) { if(pRoot.m_pLeft != null) PrintTree(pRoot.m_pLeft); if(pRoot.m_pRight != null) PrintTree(pRoot.m_pRight); } } public static void main(String[] args) { int preorder1[] = {1, 2, 4, 7, 3, 5, 6, 8}; int inorder1[] = {4, 7, 2, 1, 5, 3, 8, 6}; int preorder2[]={3,5,6}; int inorder2[]={5,3,6}; BinaryTreeNode root1 = ConstructBiTree(preorder1,0, inorder1,7, preorder1.length); BinaryTreeNode root2 = ConstructBiTree(preorder2,0, inorder2,2, preorder2.length); PrintTree(root1); PrintTree(root2); if(hasSubTree(root1,root2) System.out.println("存在子树关系!"); else System.out.println("不存在子树关系!");
}
}

 

posted @ 2015-06-18 13:20  lisahappy  阅读(172)  评论(0编辑  收藏  举报