题目:请完成一个函数,输入一棵二叉树,该函数输出它的镜像。
通过画图,我们可以很容易地发现,求解一棵二叉树的镜像,其实就是前序遍历(树根->左子树->右子树)其所有的非叶子结点,若遍历到的结点的左右子树均不为空,则交换其左右子树的位置。
对二叉树这种数据结构熟悉的读者,自然知道可以用递归的方法去遍历,也可以用循环的方法去遍历。
1.通过递归的方法
/**
public class TreeNode
{
int val = 0;//根结点的值
TreeNode left = null;//左子结点
TreeNode right = null;//右子结点
public TreeNode(int val)
{
this.val = val;
}
}
*/
public class Solution
{
public void Mirror(TreeNode root)
{
if(root == null)
return;
if(root.left == null && root.right == null)//叶子节点
return;
//前序遍历(树根->左子树->右子树)所有的非叶子结点,交换左右子树
TreeNode tmpNode = root.left;
root.left = root.right;
root.right = tmpNode;
Mirror(root.left);
Mirror(root.right);
}
}
2.通过循环的方法
这里我们可以考虑通过借助两种数据结构来实现对二叉树的遍历,分别是堆栈和队列。
堆栈是一种后入先出(LIFO)的数据结构,只能在栈顶操作数据。Stack类继承自Vector类并实现了List接口,其中该类中的主要方法如下:
Java代码如下:
//循环:堆栈
public void Mirror(TreeNode root)
{
if(root == null)
return;//如果根结点为空说明该二叉树为空
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);//把项压入堆栈顶部
TreeNode rootNode;
TreeNode tmpNode;
while(!stack.empty())//测试堆栈是否为空
{
rootNode = stack.pop();//查看并移除堆栈顶部的元素,并将其作为函数的返回值返回
if(rootNode == null)
continue;
if(rootNode.left == null && rootNode.right == null)
continue;//结束本轮循环,进行下一轮循环
tmpNode = rootNode.left;
rootNode.left = rootNode.right;
rootNode.right = tmpNode;
//堆栈后入先出
stack.push(rootNode.right);
stack.push(rootNode.left);
}
}
队列是一种先入先出(FIFO)的数据结构,只能在队列尾部添加元素,并在队列头部删除元素。Queue接口是与List接口、Set接口同一级别的接口,它们都是继承自顶层接口Collection,而我们常用的LinkedList类也实现了Queue接口。Queue接口中常用方法如下:
返回值类型 | 方法摘要 |
---|---|
boolean | add(E e) :将指定元素插入此队列,如果队列已满,则抛出IllegalStateException异常 |
E | element() :获取但不移除此队列的头,如果队列已空,则抛出NoSuchElementException异常 |
E | remove() :获取并移除此队列的头,如果队列已空,则抛出NoSuchElementException异常 |
boolean | offer(E e) :将指定元素插入此队列,如果队列已满,则返回false |
E | peek() :获取但不移除此队列的头,如果队列已空,则返回null |
E | poll() :获取并移除此队列的头,如果队列已空,则返回null |
boolean | isEmpty() :测试此队列是否为空 |
Java代码如下:
//循环:队列
public void Mirror(TreeNode root)
{
if(root == null)
return;
Queue<TreeNode> queue = new LinkedList<TreeNode>();//多态
queue.offer(root);//将指定元素插入队列
TreeNode rootNode;
TreeNode tmpNode;
while(!queue.isEmpty())//测试队列是否为空
{
rootNode = queue.poll();//获取并移除队列头部的元素
if(rootNode == null)
continue;
if(rootNode.left == null && rootNode.right == null)
continue;
tmpNode = rootNode.left;
rootNode.left = rootNode.right;
rootNode.right = tmpNode;
//队列先入先出
queue.offer(rootNode.left);
queue.offer(rootNode.right);
}
}