对于一棵二叉树,如何判断这棵二叉树是否是对称的二叉树?
例如:
从以上的图中我们可以看出,关于根节点左右对称的二叉树就是对称的二叉树,那么在程序中我们需要如何判断呢?
在二叉树的先序遍历中,先访问根结点,再访问左子树,再访问右子树。
如果是对称的二叉树,那么它的左右子树应该是一样的,也就是先访问根,再访问右子树,最后访问左子树得到的结果应该是一样的。
对于上图中的第一幅图,
先序遍历的结果是:8 6 5 7 6 7 5
对称先序遍历: 8 6 5 7 6 7 5
一样的序列,所以第一幅图是对称的二叉树。
对于第二幅图:
先序遍历的结果是:9 9 9 9 9 9
对称先序序列是: 9 9 9 9 9 9
虽然这两个序列是一样的,但是第二幅图一看就不是对称的二叉树,这就是空子树搞的事。所以,当按照两种方式进行遍历二叉树的时候,指向的结点一个为NULL一个不为NULL,那么这个二叉树一定不对称。
对于第三幅图:
先序遍历的结果是:3 4 5 6 7 6 5
对称先序序列是: 3 7 5 6 4 6 5
明显不同,所以这个二叉树也是不对称的。
鉴于以上的分析,我们可以画出这个程序的大致流程(都从根节点出发,一个先走左子树,一个先走右子树):
代码实现:
#include<iostream>
using namespace std;
template<typename T>
struct BinaryNode
{
T _data;
BinaryNode* _left;
BinaryNode* _right;
BinaryNode(const T& x = T())
:_data(x)
,_left(NULL)
,_right(NULL)
{}
};
template<typename T>
class BinaryTree
{
typedef BinaryNode<T> Node;
public:
BinaryTree(T arr[],int size,const T& invalid)
{
int index = 0;
_root = _Create(arr,size,index,invalid);
}
bool Symmetric()
{
return _Symmetric(_root,_root);
}
bool _Symmetric(Node* leftRoot,Node* rightRoot)
{
if(leftRoot == NULL && leftRoot == NULL)//访问到的都是NULL
return true;
if(leftRoot == NULL || leftRoot == NULL)//一个是NULL,一个不是
return false;
if(leftRoot->_data != rightRoot->_data)
return false;
return _Symmetric(leftRoot->_left,rightRoot->_right)
&& _Symmetric(leftRoot->_right,rightRoot->_left);
}
protected:
Node* _Create(T arr[],int size,int& index,const T& invalid)
{
Node* root = NULL;
if(index < size && arr[index] != invalid)
{
root = new Node(arr[index]);
root->_left = _Create(arr,size,++index,invalid);
root->_right = _Create(arr,size,++index,invalid);
}
return root;
}
protected:
Node* _root;
};
void Test()
{
int arr[] = {6,5,7,'#','#',3,'#','#',5,3,'#','#',7};
//int arr[] = {6,6,6,'#','#',6,'#','#',6,6,'#','#',6};
BinaryTree<int> bt(arr,sizeof(arr)/sizeof(arr[0]),'#');
cout<<(bt.Symmetric())<<endl;
}
int main()
{
Test();
system("pause");
return 0;
}