【剑指offer】判断是否是对称的二叉树

对于一棵二叉树,如何判断这棵二叉树是否是对称的二叉树?

例如:


从以上的图中我们可以看出,关于根节点左右对称的二叉树就是对称的二叉树,那么在程序中我们需要如何判断呢?
在二叉树的先序遍历中,先访问根结点,再访问左子树,再访问右子树。
如果是对称的二叉树,那么它的左右子树应该是一样的,也就是先访问根,再访问右子树,最后访问左子树得到的结果应该是一样的。
对于上图中的第一幅图,
先序遍历的结果是: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;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值