二叉树大部分都涉及到递归,因为我们无论哪种遍历方式,都要一层一层,一级一级往下深入,但是递归有的时候确是用的很头疼,所以我整理了一下二叉树的递归方法和非递归方法
package cn.hj;
import java.util.Stack;
public class hhh {
public static class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
//中序遍历
public static void Middle(TreeNode root){
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode p = root;
while(p!=null || !s.empty()){
while(p!=null){
s.push(p);
p= p.left;
}
p=s.pop();
System.out.println(p.val);
p=p.right;
}
}
//前序遍历
public static void Front(TreeNode root){
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode p = root;
while(p!=null || !s.empty()){
while(p!=null){
System.out.println(p.val);
s.push(p);
p= p.left;
}
p=s.pop();
p=p.right;
}
}
//后续遍历
public static void Behind(TreeNode root){
Stack<TreeNode> s1 = new Stack<TreeNode>();
Stack<TreeNode> s2 = new Stack<TreeNode>();
TreeNode p = root;
while(p!=null || !s1.empty()){
while(p!=null){
s1.push(p);
s2.push(p);
p= p.right;
}
p=s1.pop();
p=p.left;
}
while(!s2.empty())
System.out.println(s2.pop().val);
}
//递归前序遍历
public static void RecrusionFront(TreeNode root){
if (root!=null){
System.out.println(root.val);
RecrusionFront(root.left);
RecrusionFront(root.right);
}
}
//递归中序遍历
public static void RecrusionMiddle(TreeNode root){
if (root!=null){
RecrusionMiddle(root.left);
System.out.println(root.val);
RecrusionMiddle(root.right);
}
}
//递归后续遍历
public static void RecrusionBehind(TreeNode root){
if (root!=null){
RecrusionBehind(root.left);
RecrusionBehind(root.right);
System.out.println(root.val);
}
}
public static void main(String[] args) {
TreeNode a = new TreeNode(10);TreeNode b = new TreeNode(6);TreeNode c = new TreeNode(7);TreeNode d = new TreeNode(20);
TreeNode e = new TreeNode(5);
a.left = b;a.right=d;b.left=null;b.right=c;c.left=e;c.right=null;d.right=null;d.left=null;e.left=null;e.right = null;
// Middle(a);
//// Front(a);
//// Behind(a);
RecrusionFront(a);
}
}
大家可以看到用递归方式实现的前序,中序和后序是十分简单的,只有简单的三行代码
只需要在左子树前,左子树和右子树中间和右子树后面进行打印输出即可
下面我来给大家解释一下用栈实现的思想 代码都在上面,这里我简要的说明一下思路
栈实现前序遍历
前序 顺序是 根 左子树 右子树 但是我们不能一直往下面搜索,因为一旦到达叶子节点的时候我们还要进行回溯,所以这个时候
我们就想到了栈这种数据结构
当我们遍历的时候,我们只需要顺着左子树进行遍历,然后依次把节点打印并入栈,当到达尽头的时候,我们在弹出栈中的节点,对该节点的右子树进行同样的操作,也就是说把弹出的哪一个节点的右子树当做根在进行依次重复的操作
栈实现中序遍历
中序 顺序是 左子树 根 右子树,那么也就是说我们遇到根的时候我们不能马上输出,因为要先到达左子树的最低端,才能实现这个顺序的输出,那么我们不妨在弹出栈的时候输出,这样便实现了这个顺序
栈实现后序遍历
后序 顺序是左子树 右子树 和 根 这个也是我要重点强调的,前两种只要是对递归搞清楚了就可以轻轻松松写出来,但是这种可能么有那么简单,但是也不复杂,只需要你脑筋稍微转换一下
你看 我们不能简单的模仿前序遍历,因为如果单纯的模仿的话,就变成了从右子树开始前序遍历了(这里最好大家结合者画图再看),所以我们这个时候要实现从左边先输出的话,我们就从右边先开始,然后使用两个栈结构,一个用来树的搜索,另一个用来存储序列,当搜索的栈空了的时候,也就是说明这个序列也就直接在栈里面了,输出就行了
用一个栈也可以,但是我没有太看懂而且在思想上也比较麻烦(因为你再判断什么时候输出的时候,你需要做判断,也就是做一个标志位,当我根的左右子树都输出的时候才能打印根节点),但是这个两个栈的方法在思路上会更简单些