递归解决:
/**
* 二叉树的后序遍历
* @author Administrator
*
*/
public class TwoChaTree {
/**首先我们要明白二叉树后序遍历的定义? 先左在右最后根。 如下例子后序遍历结果为:3 2 2 1
* 举个栗子:二叉树
* 1
* 2 2
* 3
*/
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
postorderTraversal(root, list);
System.out.println(list);
return list;
}
private void postorderTraversal(TreeNode treeNode, List<Integer> list) {
if(treeNode == null) {
return;
}
/**
* 在下一行代码,我们不断的调用postorderTraversal()方法,以下简称p()方法
* 第一次调用 p(treeNode.left, list) :p(2, []),treeNode != null // 为了简写这里的2代表 下一个treeNode的val
* 第二次调用 p(treeNode.left, list) :p(3, []),第三次执行p()
* 这时treeNode == null,执行return,我们返回到第二次调用postorderTraversal(),
* 说明p(treeNode.left, list)这个方法已经执行完毕(很多人会卡在这里)
* 接着我们继续执行 p(treeNode.right, list) :treeNode.val = 3,treeNode.right = null作为参数
* 调用p(null,[]), return;
* 这里说明我们第二次调用p(treeNode.right, list)执行完毕,这时p(3, []),来到 list.add(3)
*
* 这里注意,执行完list.add(3),我们只代表执行完第二次调用p(treeNode.left, list)和p(treeNode.right, list)
* 这里我们需要返回到第二次已经调用p(treeNode.left, list)剩下的p(treeNode.right, list):p(2, [3])再次执行 第三次次调用
* p(treeNode.right, list): p(0,[3],这里return,返回第一次调用P(2,[3])并已经执行完毕,接着执行list.add(2)
*
* 这里同上,回到最初调用p(2, [3,2]);在执行list.add(2),这里postorderTraversal(treeNode.right, list)已经执行完毕,在执行list.add(1)
*
* 到这里就所有执行完毕
*
* 总结:能运行dbug运行一下
*
*/
postorderTraversal(treeNode.left, list);
postorderTraversal(treeNode.right, list);
list.add(treeNode.val);
}
public static void main(String[] args) {
TwoChaTree twoChaTree = new TwoChaTree();
twoChaTree.postorderTraversal(new TreeNode(1, new TreeNode(2,new TreeNode(3),null), new TreeNode(2)));
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
自定义栈
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* 二叉树的后序遍历
* @author Administrator
*
*/
public class TwoChaTree02 {
private class Command {
String s;
TreeNode treeNode;
public Command(String s, TreeNode treeNode) {
this.s = s;
this.treeNode = treeNode;
}
}
/**首先我们要明白二叉树后序遍历的定义? 先左在右最后根。 如下例子后序遍历结果为:3 2 2 1
* 其次我们要明白栈的一个重要定义:元素先进后出 ,所以我们设计要先push根 在push右节点,最后push做节点
* 举个栗子:二叉树
* 1
* 2 2
* 3
*/
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root == null) {
return list;
}
Stack<Command> stack = new Stack<>();
// 将栈push一个元素 : [0] s = "go",root
stack.push(new Command("go", root));
while(!stack.isEmpty()) {
/**
* 1.pop取出当前元素
* 3.因为最后push先拿出来 , 第二次取 [2]{s = go,左节点} ,stack剩余两个元素
* 5取出最后一个元素[4]s = go,treeNode != null
* 7.取出最后一个元素[6]s = go,treeNode == null,然后再取一个元素[5]s = go,treeNode == null,再取一个元素 [4]s = visit
* 9取出最后一个元素[3] s= go,这时候取的是右节点null
* 11取到 第二层的右节点
* 12 取到null 取到null 取到visit list.add(2) 最后list.add(1)
*/
Command command = stack.pop();
if("visit".equals(command.s)) {
/**
* 8.list.add(3)
* 10 list.add(2)
*/
list.add(command.treeNode.val);
}
/**
* 2.第一次push三个元素 [0] {s = visit,对象} [1]{s = go,右节点} ,[2]{s = go,左节点} 相当于 1 2 2
* 4.根据例子 stack继续增加三个元素 2 3 null
* 6根据例子 stack继续增加三个元素 3 null null
* 12 根据例子 stack继续增加三个元素 2 null null
*/
if("go".equals(command.s) && command.treeNode != null) {
stack.push(new Command("visit", command.treeNode));
stack.push(new Command("go", command.treeNode.right));
stack.push(new Command("go", command.treeNode.left));
}
}
System.out.println(list);
return list;
}
public static void main(String[] args) {
TwoChaTree02 twoChaTree = new TwoChaTree02();
twoChaTree.postorderTraversal(new TreeNode(1, new TreeNode(2,new TreeNode(3),null), new TreeNode(2)));
}
}
总结:开始不理解的话慢慢跟着dbug走,然后跟着我的注释,相信你很快就会弄懂的,还有这两种方法对前序和中序也同样适用哦!!!!!