刚学习二叉树的时候,总是要讲到对二叉树的前序、中序、后序遍历,那么应该如何实现呢?那么今天我们来用Java实现一下二叉树的递归与非递归前序、中序、后序遍历。
首先,要学会手写出一颗树的前序、中序、后序遍历序列:
前序(根左右):1 、2 、3
中序(左根右):1 、3 、2
后序(左右根):3 、2 、1
树再复杂一点:
前序(根左右):3 、9 、20、15、7
中序(左根右):9 、3 、15、20、7
后序(左右根):9 、15 、7、20、3
首先来看一种递归方式的解法,代码及其简单:
TreeNode结构体:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
递归前序遍历:
public static void preorder(TreeNode root) {
if(root == null) {
return;
}
System.out.println(root.val);
preorder(root.left);
preorder(root.right);
}
递归中序遍历:
public static void inorder(TreeNode root) {
if(root == null) {
return;
}
inorder(root.left);
System.out.println(root.val);
inorder(root.right);
}
递归后序遍历:
public static void aforder(TreeNode root) {
if(root == null) {
return;
}
aforder(root.left);
aforder(root.right);
System.out.println(root.val);
}
大家发现有什么不同了吗?
前序遍历时,输出语句是不是在递归调用左子树前
中序遍历时,输出语句是不是在递归调用左子树和递归调用右子树中间
后序遍历时,输出语句是不是在递归调用右子树后
为什么会这样呢?这里留个悬念,可以仔细思考一下。
接下来讲一下非递归方式的写法:
前序遍历:需要一个栈,如果右子树不空,先压右子树,然后压左子树
非递归前序遍历:
public static List<Integer> preorderTraversal2(TreeNode root) {
List list = new LinkedList();
if(root != null) {
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.add(root);
while ( !stack.isEmpty() ) {
root = stack.pop();
list.add(root.val);
System.out.println(root.val);
if(root.right != null) {
stack.push(root.right);
}
if(root.left != null){
stack.push(root.left);
}
}
}
return list;
}
中序遍历:需要一个栈,如果左子树不空,一直压左子树,直到左子树为空时压右子树,遇右子树弹栈
public static List<Integer> inorderTraversal2(TreeNode root) {
List list = new LinkedList();
Stack<TreeNode> stack = new Stack<TreeNode>();
if (root != null) {
while ( !stack.isEmpty() || root != null) {
if(root != null) {
stack.push(root);
root = root.left;
}
else {
root = stack.pop();
list.add(root.val);
root = root.right;
}
}
}
return list;
}
后序遍历:需要两个栈,如果左子树不空,先压左子树,后压右子树,压出值放在另一个栈中
public static List<Integer> aforderTraversal2(TreeNode root) {
List list = new LinkedList();
Stack<TreeNode> stack1 = new Stack<TreeNode>();
Stack<TreeNode> stack2 = new Stack<TreeNode>();
if(root != null) {
stack1.add(root);
while ( !stack1.isEmpty() ) {
TreeNode cur = stack1.pop();
stack2.add(cur);
if(cur.left != null) {
stack1.push(cur.left);
}
if(cur.right != null){
stack1.push(cur.right);
}
}
}
while ( !stack2.isEmpty() ) {
list.add(stack2.pop().val);
}
return list;
}