• 二叉树(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;
    }




  • 相关阅读:
    Fedora 12/Debian 以root登录图形界面
    贡献一个简单的日志类
    "没有 pthread_create 的手册页条目"解决办法
    OpenBSD 下架设vsftpd
    NetSnmp初步(一):让我们的程序提供snmp服务
    linux socket接收、发送小工具(支持tcp、udp包(组播)的发送接收)
    NetSnmp初步(二):发送Notification
    netbeans添加现有源文件时自动更新Makefile依赖关系
    Fedora Core12的防火墙会过滤掉部分IP数据包,在开发调试时建议关闭防火墙
    NetSnmp初步(三):接收控制命令:实现SNMP的SET命令
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5134278.html
Copyright © 2020-2023  润新知