题目描述
操作给定的二叉树,将其变换为源二叉树的镜像。
分析
二叉树的镜像即交换二叉树左右子树,如下图
1、递归
public class Solution {
/**
二叉树的镜像即交换左右子树,每个节点的左右子树都交换,做这种重复性动作,我们可以想到递归
递归遍历二叉树就用前序遍历
*/
public void Mirror(TreeNode root) {
if(root != null){
TreeNode temp=null;
temp = root.left;
root.left = root.right;
root.right = temp;
Mirror(root.left);
Mirror(root.right);
}
}
}
2、非递归(借助栈),注意栈是先进后出的,所以想先序遍历(根左右),子树必须入栈顺序是右左,这样出栈后才会是左右
import java.util.Stack;
public class Solution {
public void Mirror(TreeNode root) {
if(root != null){
TreeNode temp=null;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root); //根节点入栈
while(!stack.isEmpty()){
TreeNode node = stack.pop(); //根节点出栈
temp = node.left; //交换node左右子树
node.left = node.right;
node.right = temp;
if(node.right != null){
stack.push(node.right); //右子树入栈
}
if(node.left != null){
stack.push(node.left); //左子树出栈
}
}
}
}
}
递归与非递归对比
(1)递归更消耗内存,递归无非是程序调用自身,程序运行时代码和数据存到内存中,即要分配内存空间,递归程序每调用一次自身,操作系统都要为其分配相应的内存资源,这一过程是通过“工作栈”这种数据结构实现的,当重复调用几十层以上的话,栈上堆满了本地变量,但是程序不停,它就不会释放,占着的内存资源,内存就会消耗很大,但递归有个优点就是代码简单、短。
(2)非递归主要用循环,循环则不同,循环得每次执行是对已有变量的更新,一般不会产生大量重复的东西,不会产生堆积占内存,从而节省内存。
通过上述描述,我们发现非递归对内存友好,如上面两程序运行后,得到两个程序运行时间和资源消耗结果图,我们看到时间消耗差不多一样,但非递归反而大,这不违背了吗,自己刚说的打脸了?事实上是我们这个实验数据还是太小,递归重复次数也就几次,不多,所以看不出,只有数据比较大时,递归层数比较多时,如几十、几百次递归,这才能看出二者区别了,这个时候肯定非递归优势明显。