题目描述

操作给定的二叉树,将其变换为源二叉树的镜像。

Apache NetBeans镜像_java

分析

二叉树的镜像即交换二叉树左右子树,如下图

Apache NetBeans镜像_java_02

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);
        }
    }
}

Apache NetBeans镜像_二叉树_03

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); //左子树出栈
        		}
        	}
        }
    }
}

Apache NetBeans镜像_Apache NetBeans镜像_04


递归与非递归对比

(1)递归更消耗内存,递归无非是程序调用自身,程序运行时代码和数据存到内存中,即要分配内存空间,递归程序每调用一次自身,操作系统都要为其分配相应的内存资源,这一过程是通过“工作栈”这种数据结构实现的,当重复调用几十层以上的话,栈上堆满了本地变量,但是程序不停,它就不会释放,占着的内存资源,内存就会消耗很大,但递归有个优点就是代码简单、短。

(2)非递归主要用循环,循环则不同,循环得每次执行是对已有变量的更新,一般不会产生大量重复的东西,不会产生堆积占内存,从而节省内存。

通过上述描述,我们发现非递归对内存友好,如上面两程序运行后,得到两个程序运行时间和资源消耗结果图,我们看到时间消耗差不多一样,但非递归反而大,这不违背了吗,自己刚说的打脸了?事实上是我们这个实验数据还是太小,递归重复次数也就几次,不多,所以看不出,只有数据比较大时,递归层数比较多时,如几十、几百次递归,这才能看出二者区别了,这个时候肯定非递归优势明显。