剑指offer面试题19之求二叉树的镜像
一.问题描述
给定一颗二叉树如何求该二叉树的镜像?
二叉树的结点结构如下:
template<class T>
struct TreeNode
{
TreeNode(const T& data)
:_data(data)
,_left(NULL)
,_right(NULL)
{}
T _data;
TreeNode<T> *_left;
TreeNode<T> *_right;
};
二.问题分析
对于二叉树相信学过数据结构的童鞋都不陌生,那仫什仫是二叉树的镜像呢?给定一颗二叉树如何求取它的镜像二叉树呢?这就是我今天要解决的问题.
要理解镜像这个概念我们可以类比镜子的原理,下图是我自己画的一颗二叉树和它的镜像:
通过观察上述两颗树我发现:这两颗树具有相同的根结点;左右子节点交换了位置。于是我得到下列求二叉树镜像的步骤:
1.根结点保持不变
2.交换根结点的左右子树
3.交换步骤2完成之后的左结点(也就是结点10,读者可自行画图)的左右子结点
4.交换步骤2完成之后的右结点(就是结点6)的左右子节点
通过总结上面的步骤哦得到了求取一颗二叉树镜像的步骤:先序遍历这颗树的所有节点,如果遍历到的结点存在子节点就交换子节点,当交换完所有子节点的非叶子节点的左右子节点之后就求出了这颗树的镜像二叉树了。
三.代码实现
1.递归实现
void GetBinaryTreeShadow(Node *root)
{
if(NULL == root)
return ;
if((NULL == root->_left) && (NULL == root->_right))
return ;
Node *tmp=root->_left;
root->_left=root->_right;
root->_right=tmp;
if(root->_left)
GetBinaryTreeShadow(root->_left);
if(root->_right)
GetBinaryTreeShadow(root->_right);
}
2.非递归实现
当我参考剑指offer实现完递归版本的二叉树镜像之后我实现了上述递归版本的代码,那仫如何实现非递归版本的呢?也就是剑指上所说的如何使用循环实现?刚开始确实没有什仫头绪,这几日我一直在复习之前实现的代码发现在二叉树的非递归实现前序,中序,后序遍历中用到了栈来实现,那仫这个求二叉树镜像是否也可以通过栈来实现呢?我们可以让原始二叉树的根节点先入栈作为镜像二叉树的根节点,如果该节点的子树不为空的话就交换节点并入栈。实现代码如下:
void GetBinaryTreeShadow(Node *root)
{
if(NULL == root)
return ;
stack<Node *> s;
s.push(root);
while(s.size())
{
Node *root=s.top();
s.pop();
if(root->_left || root->_right)
{
Node *tmp=root->_left;
root->_left=root->_right;
root->_right=tmp;
}
if(root->_left)
s.push(root->_left);
if(root->_right)
s.push(root->_right);
}
}
测试实例:普通的二叉树,只有左子树的二叉树,只有右子树的二叉树以及只有根结点来测试都是可实现的。
总结:
这道剑指面试题其实并没有太难以解决,只是它的题目中出现的新名词-镜像,二叉树的镜像是一个抽象的概念,它的难点在于将抽象的问题形象化,这通常也是面试官常考的关于应试者的发散思维的一类题目.~~~~