一、前言
《二叉树的镜像》在验证二叉树是互为镜像时,给出了三种方法,本文对这三种方法进行说明
二、题目
判断两颗二叉树是否互为镜像。
三、思路
三种解决方法:
方法一,将其中一颗二叉树转为镜像,并与另外一棵树进行比较判断各节点值是否相等
方法二,互为镜像的两个二叉树,每层数据顺序相反,逐层判断即可,需要注意结点为空的情况。前面文章中《从上往下打印二叉树》给出了获得逐层获得树数据方法。
方法三:递归实现——树1左结点和树2右结点判断;树1右结点和树2左结点判断。
三种方法特点:
方法一:在《二叉树的镜像》基础上可以得到镜像,比较两个镜像树结点是否相等,理解了《二叉树的镜像》,这种方法也就很好理解
方法二:互为镜像的二叉树,每层数据顺序相反,直接判断即可,易于理解但是获得每层数据和比较相等麻烦些。
方法三种:思路相对抽象,编码简单。
四、编码实现
//==========================================================================
/**
* @file : MirrorOfBinaryTreeJudge.h
* @purpose : 输入两棵二叉树A和B,判断B是不是A的子结构。
*
* 有三种解决方案
*/
//==========================================================================
#pragma once
#include "MirrorOfBinaryTree.h"
// 判断二个二叉树是否相等(所有结点相等)
template<class T>
bool BinaryTreeEqual(BinaryTreeNode<T>* pRootA, BinaryTreeNode<T>* pRootB)
{
if (pRootA == nullptr && pRootB == nullptr)
{
return true;
}
else if (pRootA != nullptr && pRootB != nullptr)
{
return BinaryTreeEqual(pRootA->m_pLeft, pRootB->m_pLeft) && BinaryTreeEqual(pRootA->m_pRight, pRootB->m_pRight);
}
else
{
return false;
}
}
////////////////////// 方法一 ///////////////////////////////////////
// 方法一
// 思路:先将其中一个树转为镜像再与另外一棵树进行比较,相等则互为镜像
template<class T>
bool MirrorOfBinaryTreeJudge_Solution1(BinaryTreeNode<T>* pRootA, BinaryTreeNode<T>* pRootB)
{
// 约定两个空树不互为镜像
if (pRootA == nullptr || pRootB == nullptr)
{
return false;
}
MirrorOfBinaryTree(pRootA); // 将pRootA,转为镜像,若pRootA和pRootB结点值相等则pRootA和pRootB互为镜像
bool result = BinaryTreeEqual(pRootA, pRootB);
MirrorOfBinaryTree(pRootA); // 有前面将pRootA转为了镜像,此处需要回复他的镜像
return result;
}
////////////////////// 方法二 ///////////////////////////////////////
// 方法二
// 思路:互为镜像的特定是,每一层数据顺序相反。需要考虑到结点为空的情况。
template<class T>
bool MirrorOfBinaryTreeJudge_Solution2(BinaryTreeNode<T>* pRootA, BinaryTreeNode<T>* pRootB)
{
// 约定两个空树不互为镜像
if (pRootA == nullptr || pRootB == nullptr)
{
return false;
}
map<int, vector<BinaryTreeNode<T>*>> dataA; //记录的是每行节点值
GetTreesInLines(pRootA, dataA);
map<int, vector<BinaryTreeNode<T>*>> dataB; //记录的是每行节点值
GetTreesInLines(pRootB, dataB);
// 判断两个二叉树是否互为镜像
bool result = true;
if (dataA.size() == dataB.size())
{
auto itA = dataA.begin();
auto itB = dataB.begin();
for (size_t i = 0; i < dataA.size(); i++, itA++, itB++)
{
if (itA->second.size() == itB->second.size())
{
size_t len = itA->second.size();
for (size_t j = 0; j < len; j++)
{
size_t tailIndex = len - 1 - j;
if (itA->second[j] == nullptr && itB->second[tailIndex] == nullptr)
{
continue;
}
else if (itA->second[j] != nullptr && itB->second[tailIndex] != nullptr)
{
if (itA->second[j]->m_nValue != itB->second[tailIndex]->m_nValue)
{
result = false;
break;
}
}
else
{
result = false;
break;
}
}
if (!result)
{
break;
}
}
else
{
result = false;
}
}
}
else
{
result = false;
}
return result;
}
////////////////////// 方法三 ///////////////////////////////////////
// 方法三
// 思路:镜像树特点,左子树为镜像树右子树;右子树为镜像树左子树
template<class T>
bool MirrorOfBinaryTreeJudge_Solution3_Operate(BinaryTreeNode<T>* pRootA, BinaryTreeNode<T>* pRootB);
template<class T>
bool MirrorOfBinaryTreeJudge_Solution3(BinaryTreeNode<T>* pRootA, BinaryTreeNode<T>* pRootB)
{
// 约定两个空树不互为镜像
if (pRootA == nullptr || pRootB == nullptr)
{
return false;
}
return MirrorOfBinaryTreeJudge_Solution3_Operate(pRootA, pRootB);
}
template<class T>
bool MirrorOfBinaryTreeJudge_Solution3_Operate(BinaryTreeNode<T>* pRootA, BinaryTreeNode<T>* pRootB)
{
// 约定两个空树不互为镜像
if (pRootA == nullptr && pRootB == nullptr)
{
return true;
}
if (pRootA == nullptr || pRootB == nullptr)
{
return false;
}
if (pRootA->m_nValue != pRootB->m_nValue)
{
return false;
}
return MirrorOfBinaryTreeJudge_Solution3_Operate(pRootA->m_pLeft, pRootB->m_pRight)
&& MirrorOfBinaryTreeJudge_Solution3_Operate(pRootA->m_pRight, pRootB->m_pLeft);
}
// 测试用例见 《二叉树的镜像》
二叉树的镜像: https://blog.csdn.net/nie2314550441/article/details/106183227