判断二叉树是否是对称的--以根节点的中线为轴

 


描述:

请判断一个二叉树是否是对称的(以根节点的中线为轴), 例如,如下的则是对称的:

 


方案1:
基于循环法进行树的广度优先遍历,左右子树分别单独遍历,并将节点保存到vector中. 对于左子树的各个层,我们总是先访问左侧的节点, 对于右子树的各个层,我们总是先访问右侧的节点。最后比较左右子树的vector中的元素是否对应相等.如果树是对称的,则必定相等。

缺点是: 需要额外的空间较多。首先,树的广度优先遍历使用了queue, 然后为了保存节点,使用了vector。

引申:对于左子树进行 深度优先遍历中的(根节点-左节点-右节点),
           对于右子树进行 深度优先遍历中的(根节点-右节点-左节点)也可以。


方案2:
对上面方法改进一下:不借助额外的vector, 对根节点的左右子树同步进行广度优先遍历!一边遍历 一遍比较。


方案3:
基于递归的方法.  能否想到的关键是递归函数右两个入参,pLeft 和pRight。 juege_recusive(Node* leftNode, Node* rightNode)。


相似:

二叉树的镜像:https://blog.csdn.net/qq_35865125/article/details/79339200


代码:

#pragma once
#include <vector>
#include <iostream>
#include <queue>
using namespace std;

class SysmetricTreeJudge
{
public:
    struct Node {
        Node(int v=0, Node* pLeft=nullptr, Node* pRight = nullptr):
        val(v),
        pL(pLeft),
        pR(pRight){

        }
        int val;
        Node* pL;
        Node* pR;
    };
    //方案1: ---------------------------------------------------------------------
    //基于循环法进行树的广度优先遍历,左右子树分别单独遍历,并将节点保存到vector中. 对于左子树的各个层,我们
    //总是先访问左侧的节点, 对于右子树的各个层,我们总是先访问右侧的节点。最后比较左右子树的vector中
    //的元素是否对应相等.如果树是对称的,则必定相等。
    //缺点是: 需要额外的空间较多。首先,树的广度优先遍历使用了queue, 然后为了保存节点,使用了vector。
    //引申: 对于左子树进行 深度优先遍历中的(根节点-左节点-右节点),
    //       对于右子树进行 深度优先遍历中的(根节点-右节点-左节点)也可以。
    bool judge_while(Node* root) {

        if (!root)
            return false;
        Node* leftTree = root->pL;
        Node* rightTree = root->pR;
        vector<int> leftTreeVec;
        vector<int> rightTreeVec;

        queue<Node*> leftTreeQue;
        queue<Node*> rightTreeQue;

        leftTreeQue.push(leftTree);
        while (!leftTreeQue.empty()) {
            Node* p = leftTreeQue.front();
            leftTreeQue.pop();
            leftTreeVec.push_back(p->val);
            if (p->pL)  //从左向右访问同一层的节点
                leftTreeQue.push(p->pL);
            if (p->pR)
                leftTreeQue.push(p->pR);
        }

        rightTreeQue.push(rightTree);
        while (!rightTreeQue.empty()) {
            Node* p = rightTreeQue.front();
            rightTreeQue.front();
            rightTreeQue.pop();
            rightTreeVec.push_back(p->val);
            if (p->pR)  // 从右向左访问同一层的节点
                rightTreeQue.push(p->pR);
            if (p->pL)
                rightTreeQue.push(p->pL);
        }

        int leftTreeSize = leftTreeVec.size();
        int rightTreeSize = rightTreeVec.size();
        if (leftTreeSize != rightTreeSize) {
            return false;
        }
        for (int idx = 0; idx < leftTreeSize; ++idx) {
            if (leftTreeVec[idx] != rightTreeVec[idx])
                return false;
        }
        return true;
    }

    //方案2: ---------------------------------------------------------------------
    //对上面方法改进一下:不借助额外的vector, 对根节点的左右子树同步进行广度优先遍历!
    //一边遍历 一遍比较。
    bool judge_while_syn(Node* root) {

        if (!root)
            return false;
        Node* leftTree = root->pL;
        Node* rightTree = root->pR;
        vector<int> leftTreeVec;
        vector<int> rightTreeVec;

        queue<Node*> leftTreeQue;
        queue<Node*> rightTreeQue;

        leftTreeQue.push(leftTree);
        rightTreeQue.push(rightTree);
        while (!leftTreeQue.empty() || !rightTreeQue.empty()) {

            if (leftTreeQue.size() != rightTreeQue.size())
                return false;

            Node* pLeftTree = leftTreeQue.front();
            leftTreeQue.pop();
            Node* pRightTree = rightTreeQue.front();
            rightTreeQue.pop();

            if (pLeftTree->val != pRightTree->val)
                return false;

            if (pLeftTree->pL)  //对于左子树 从左向右访问同一层的节点
                leftTreeQue.push(pLeftTree->pL);
            if (pLeftTree->pR)
                leftTreeQue.push(pLeftTree->pR);

            if (pRightTree->pR)  //对于右子树 从右向左访问同一层的节点
                rightTreeQue.push(pRightTree->pR);
            if (pRightTree->pL)
                rightTreeQue.push(pRightTree->pL);
        }

       
        while (!rightTreeQue.empty()) {
            Node* p = rightTreeQue.front();
            rightTreeQue.front();
            rightTreeQue.pop();
            rightTreeVec.push_back(p->val);
            if (p->pR)  // 从右向左访问同一层的节点
                rightTreeQue.push(p->pR);
            if (p->pL)
                rightTreeQue.push(p->pL);
        }

        int leftTreeSize = leftTreeVec.size();
        int rightTreeSize = rightTreeVec.size();
        if (leftTreeSize != rightTreeSize) {
            return false;
        }
        for (int idx = 0; idx < leftTreeSize; ++idx) {
            if (leftTreeVec[idx] != rightTreeVec[idx])
                return false;
        }
        return true;
    }


    //方案3:    ---------------------------------------------------------------------
    //基于递归的方法.
    bool  juege_recusive_wrapper(Node* root) {
        if (!root)
            return false;
        return juege_recusive(root->pL, root->pR);
    }
    bool  juege_recusive(Node* leftNode, Node* rightNode) {
        if (!leftNode && !rightNode) {
            return true;
        }
        if (leftNode && rightNode) {
            if (leftNode->val != rightNode->val) {
                return false;
            }
            //leftNode的左子树与rightNode的右子树进行比较
            //leftNode的右子树与rightNode的左子树进行比较:
            return juege_recusive(leftNode->pL, rightNode->pR) && juege_recusive(leftNode->pR, rightNode->pL);
        }
        else {
            return false;
        }
    }
    
//------------------------------------------------------------------------
//------------------------------------------------------------------------
    void Test_judge_while() {
        Node* root = new Node(0);
        root->pL = new Node(1);
        root->pR = new Node(1);
        root->pL->pL = new Node(11);
        root->pL->pR = new Node(12);
        root->pR->pL = new Node(12);
        root->pR->pR = new Node(11);

        root->pR->pL->pL = new Node(33);

        bool result = judge_while(root);
        return;
    }

    void Test_judge_while_syn() {
        Node* root = new Node(0);
        root->pL = new Node(1);
        root->pR = new Node(1);
        root->pL->pL = new Node(11);
        root->pL->pR = new Node(12);
        root->pR->pL = new Node(12);
        root->pR->pR = new Node(11);

        //root->pR->pL->pL = new Node(33);

        bool result = judge_while_syn(root);
        return;
    }

    void Test_juege_recusive() {
        Node* root = new Node(0);
        root->pL = new Node(1);
        root->pR = new Node(1);
        root->pL->pL = new Node(11);
        root->pL->pR = new Node(12);
        root->pR->pL = new Node(12);
        root->pR->pR = new Node(11);

        //root->pR->pL->pL = new Node(33);
        bool res = juege_recusive_wrapper(root);

        return;
    }
};

void main() {
    SysmetricTreeJudge obj;
    obj.Test_judge_while();
    obj.Test_judge_while_syn();
    obj.Test_juege_recusive();
}

 


风中的蒲公英:https://music.163.com/#/song?id=28160231&market=baiduqk

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

First Snowflakes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值