zoukankan      html  css  js  c++  java
  • 二叉树(10)----比較两个二叉树是否同样(结构和数据),递归和非递归

    1、二叉树定义

    typedef struct BTreeNodeElement_t_ {
        void *data;
    } BTreeNodeElement_t;
    
    
    typedef struct BTreeNode_t_ {
        BTreeNodeElement_t     *m_pElemt;
        struct BTreeNode_t_    *m_pLeft;
        struct BTreeNode_t_    *m_pRight;
    } BTreeNode_t;


    2、比較两个二叉树结构是否同样,不涉及存储的数据

    (1)递归方式

    假设两个二叉树pRoot都为空树,则自然同样,返回true。

    假设两个二叉树pRoot一个为空树,还有一个不为空树。则不同样,返回false;

    假设两个二叉树都不为空树。则须要分别比較左右子树后,依据比較结果共同判定。仅仅要有一个为false,则返回false。


    bool  BTreeCompare( BTreeNode_t *pRoot1, BTreeNode_t *pRoot2)
    {
        //假设都为空树,则同样
        if( pRoot1 == NULL && pRoot2 == NULL )
            return true;
        //假设一个为空。一个不为空。则不同样
        if( ( pRoot1 != NULL && pRoot2 == NULL )  ||
            ( pRoot1 == NULL && pRoot2 != NULL ) )
            return false;
        //假设都不为空,则 须要比較左右子树后,再依据比較结果断定
        bool  leftCmp = BTreeCompare( pRoot1->m_pLeft, pRoot2->m_pLeft);
        bool  rightCmp = BTreeCompare( pRoot1->m_pRight, pRoot2->m_pRight);
    
        return ( leftCmp && rightCmp );
    }

    (2)非递归方式

    借助队列实现

    实现算法:

    首先将给定根节点pRoot1和pRoot2都入队

    第一步:当两个队列未空时,分别获取两个树的当前层次中节点总数(即当前队列中节点个数)。先比較节点个数是否同样,假设不同样,则两个树自然不同;假设节点个数同样,须要出队进行比較。

    假设有一个队列未空,则退出比較。

    第二步:假设有一个队列未空,则清空队列并返回不同。


    bool  BTreeCompare(BTreeNode_t *pRoot1, BTreeNode_t *pRoot2)
    {
        if( pRoot1 == NULL && pRoot2 == NULL )
            return false;
    
        queue <BTreeNode_t *> que1;
        queue <BTreeNode_t *> que2;
    
        que1.push(pRoot1);
        que2.push(pRoot2);
    
        int curLevelNodeTotal1 = 0;
        int curLevelNodeTotal2 = 0;
    
        bool flag = true; //作为比較不一致时跳出标识
        while( ( !que1.empty()) && ( !que2.empty())) //当两个队列均不为空时。才进行比較
        {
            curLevelNodeTotal1 = que1.size();  //获取树1的当前层节点总数
            curLevelNodeTotal2 = que2.size(); //获取树2的当前层节点总数
            if( curLevelNodeTotal1 != curLevelNodeTotal2){
                flag = false;//当前层节点总数都不一致,不须要比較了,直接跳出
                break;
            }
            int cnt1 = 0;//遍历本层节点时的计数器
            int cnt2 = 0;
            while( cnt1 < curLevelNodeTotal1  && cnt2 < curLevelNodeTotal2){
                ++cnt1;
                ++cnt2;
                pRoot1 = que1.front();
                que1.pop();
                pRoot2 = que2.front();
                que2.pop();
    
                //推断pRoot1和pRoot2左右节点结构是否同样
                if( ( pRoot1->m_pLeft != NULL && pRoot2->m_pLeft == NULL )    ||
                    ( pRoot1->m_pLeft == NULL && pRoot2->m_pLeft != NULL )    ||
                    ( pRoot1->m_pRight != NULL && pRoot2->m_pRight == NULL )    ||
                    ( pRoot1->m_pRight == NULL && pRoot2->m_pRight != NULL )
                ){
                    flag = false;
                    break;
                }
     
                //将左右节点入队
                if( pRoot1->m_pLeft != NULL )
                    que1.push( pRoot1->m_pLeft);
                if( pRoot1->m_pRight != NULL )
                    que1.push( pRoot1->m_pRight);
                if( pRoot2->m_pLeft != NULL )
                    que2.push( pRoot2->m_pLeft);
                if( pRoot2->m_pRight != NULL )
                    que2.push( pRoot2->m_pRight);
            }
    
            if( flag == false )
                break;
        }
    
        //假设比較标志为false。则不同样
        if( flag == false ){
            while( !que1.empty() )
                que1.pop();
            while( !que2.empty())
                que2.pop();
    
            return false;
        }
    
        return true;
    }


    3、比較两个二叉树结构和数据是否同一时候同样。即两个一模一样的树

    与上面的不同之处在于:在比較结构是否同样之后。须要比較当前节点的数据是否一致。

    算法是一致的,仅仅须要加入一行代码就可以。


    (1)递归方式:

    bool  BTreeCompare( BTreeNode_t *pRoot1, BTreeNode_t *pRoot2)
    {
        //假设都为空树,则同样
        if( pRoot1 == NULL && pRoot2 == NULL )
            return true;
        //假设一个为空。一个不为空,则不同样
        if( ( pRoot1 != NULL && pRoot2 == NULL )  ||
            ( pRoot1 == NULL && pRoot2 != NULL ) )
            return false;
        //比較当前节点中的数据
        if( pRoot1->m_pElemt != pRoot2->m_pElemt)
            return false;
        //假设都不为空。则 须要比較左右子树后。再依据比較结果断定
        bool  leftCmp = BTreeCompare( pRoot1->m_pLeft, pRoot2->m_pLeft);
        bool  rightCmp = BTreeCompare( pRoot1->m_pRight, pRoot2->m_pRight);
    
        return ( leftCmp && rightCmp );
    }


    (2)非递归方式

    bool  BTreeCompare(BTreeNode_t *pRoot1, BTreeNode_t *pRoot2)
    {
        if( pRoot1 == NULL && pRoot2 == NULL )
            return false;
    
    
        queue <BTreeNode_t *> que1;
        queue <BTreeNode_t *> que2;
    
    
        que1.push(pRoot1);
        que2.push(pRoot2);
    
    
        int curLevelNodeTotal1 = 0;
        int curLevelNodeTotal2 = 0;
    
    
        bool flag = true; //作为比較不一致时跳出标识
        while( ( !que1.empty()) && ( !que2.empty())) //当两个队列均不为空时,才进行比較
        {
            curLevelNodeTotal1 = que1.size();  //获取树1的当前层节点总数
            curLevelNodeTotal2 = que2.size(); //获取树2的当前层节点总数
            if( curLevelNodeTotal1 != curLevelNodeTotal2){
                flag = false;//当前层节点总数都不一致。不须要比較了,直接跳出
                break;
            }
            int cnt1 = 0;//遍历本层节点时的计数器
            int cnt2 = 0;
            while( cnt1 < curLevelNodeTotal1  && cnt2 < curLevelNodeTotal2){
                ++cnt1;
                ++cnt2;
                pRoot1 = que1.front();
                que1.pop();
                pRoot2 = que2.front();
                que2.pop();
    
                //比較当前节点中数据是否一致
                if( pRoot1->m_pElemt != pRoot2->m_pElemt ){
                    flag = false;
                    break;
                }
                //推断pRoot1和pRoot2左右节点结构是否同样
                if( ( pRoot1->m_pLeft != NULL && pRoot2->m_pLeft == NULL )    ||
                    ( pRoot1->m_pLeft == NULL && pRoot2->m_pLeft != NULL )    ||
                    ( pRoot1->m_pRight != NULL && pRoot2->m_pRight == NULL )    ||
                    ( pRoot1->m_pRight == NULL && pRoot2->m_pRight != NULL )
                ){
                    flag = false;
                    break;
                }
     
                //将左右节点入队
                if( pRoot1->m_pLeft != NULL )
                    que1.push( pRoot1->m_pLeft);
                if( pRoot1->m_pRight != NULL )
                    que1.push( pRoot1->m_pRight);
                if( pRoot2->m_pLeft != NULL )
                    que2.push( pRoot2->m_pLeft);
                if( pRoot2->m_pRight != NULL )
                    que2.push( pRoot2->m_pRight);
            }
    
    
            if( flag == false )
                break;
        }
    
        //假设比較标志为false。则不同样
        if( flag == false ){
            while( !que1.empty() )
                que1.pop();
            while( !que2.empty())
                que2.pop();
    
    
            return false;
        }
    
    
        return true;
    }




  • 相关阅读:
    Effective Java 第三版——72. 赞成使用标准异常
    Effective Java 第三版——71. 避免不必要地使用检查异常
    Effective Java 第三版——70. 对可恢复条件使用检查异常,对编程错误使用运行时异常
    Effective Java 第三版——69. 仅在发生异常的条件下使用异常
    Effective Java 第三版——68. 遵守普遍接受的命名约定
    Effective Java 第三版——67. 明智谨慎地进行优化
    Effective Java 第三版——66. 明智谨慎地使用本地方法
    Effective Java 第三版——65. 接口优于反射
    Effective Java 第三版——64. 通过对象的接口引用对象
    Effective Java 第三版——63. 注意字符串连接的性能
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5134278.html
Copyright © 2011-2022 走看看