zoukankan      html  css  js  c++  java
  • 剑指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
    ", pNode->m_nValue);  
            if(pNode->m_pLeft != NULL)  
                printf("value of its left child is: %d.
    ", pNode->m_pLeft->m_nValue);  
            else 
                printf("left child is null.
    ");  
            if(pNode->m_pRight != NULL)  
                printf("value of its right child is: %d.
    ", pNode->m_pRight->m_nValue);  
            else 
                printf("right child is null.
    ");  
        }  
        else 
        {  
            printf("this node is null.
    ");  
        }  
        printf("
    ");  
    }  
     
    //递归打印左右子树
    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. "); if(pNode.m_pRight != null) System.out.println("right child is:"+pNode.m_pRight.m_nValue); else System.out.println("right child is null. "); } else { System.out.println("this node is null. "); } 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("不存在子树关系!");
    }
    }
  • 相关阅读:
    Linux上传下载文件(rz/sz)
    注册页面(函数调用,数组,对象,for,innerHTML)
    课程表(点击事件,for)
    winform中固定界面大小的方法
    VS常用快捷键
    Python的标准输出
    Spring注解驱动第二讲--@ComponentScan扫描介绍
    Spring注解驱动第一讲--Spring环境搭建
    通用目标检测
    通用目标检测-发展趋势
  • 原文地址:https://www.cnblogs.com/hupp/p/4585617.html
Copyright © 2011-2022 走看看