基本的二叉树遍历分为中序,后序和前序遍历。对他们的遍历又有递归和非递归两种方式。本文主要会涉及两种方式的二叉树遍历,会详细阐述二叉树的非递归遍历方式。
二叉树递归遍历方式
这种方式比较简单,下面是实现的代码: 结点类: TreeNode.java
private class TreeNode{
private String value=null;
private TreeNode left=null;
private TreeNode right=null;
public TreeNode(){}
/**
* @param value 数据
*/
public TreeNode(String value){
this.value=value;
this.left=null;
this.right=null;
}
}
二叉树前序递归遍历方式:
public void preOrder(TreeNode node){
if(subTree!=null){
System.out.println(node.value + " ");
preOrder(subTree.left);
preOrder(subTree.right);
}
}
后序和中序遍历就是把输出语句分别放到第五行和第4行,没什么说的。
二叉树非递归遍历
这是重头戏,比较难的。其中后序遍历二叉树的非递归算法最为复杂。下面详细介绍:
前序遍历:
先贴出代码:
public void PreOrderWithoutRec(TreeNode head){
System.out.println("前序遍歷的非遞歸實現:");
if (head != null) {
Stack<TreeNode> stack = new Stack<>();
stack.add(head);
while (!stack.isEmpty()) {
head = stack.pop();
System.out.println(head.value + " ");
if (head.right != null) {
stack.push(head.righ);
}
if (head.left != null) {
stack.push(head.left);
}
}
}
System.out.println();
}
思路: 1)申请一个新的栈, 记为stack,然后将头结点压入stack中。 2)从stack中取出栈顶结点,打印,先将其右孩子推入栈中,再将左孩子压入栈中。 3)不断重复2)直到stack为空为止。
中序遍历
先提出代码:
public void nonRecInOrder(TreeNode head){
System.out.println("中序遍歷");
if (head != null) {
Stack<TreeNode> stack = new Stack<>();
while (!stack.isEmpty() || head != null) {
if (head != null) {
stack.add(head);
head = head.left;
} else {
head = stack.pop();
System.out.println(head.value + " ");
head = head.right;
}
}
}
}
思路: 1)申请一个新的栈stack,初始是将头节点压入stack中 2)依次把head的左节点复制给head。重复,直到head为空。 3)从stack中取出结点并打印,并让head=head.right,重复2) 就是无论如何都要现打印左子树。
后序遍历
这种比较复杂,我用两个Stack来实现: 贴出代码:
public void PostOrderWithoutRec(TreeNode head){
System.out.println("後序遍歷方法1");
if (head != null) {
Stack<TreeNode> s1 = new Stack<>();
Stack<TreeNode> s2 = new Stack<>();
s1.push(head);
while (!s1.isEmpty()) {
TreeNode node = s1.pop();
s2.push(node);
if (node.left != null)
s1.push(node.left);
if (node.right != null)
s1.push(node.right);
}
while (!s2.isEmpty()) {
System.out.println(s2.pop().value + " ");
}
}
}
思路: 1)申请两个栈s1,s2.先将head压入s1. 2)从s1弹出结点,放入head中并将左右孩子分别压入栈中。 3)对于s2.在整个过程中,将每一个从s1弹出的结点都放进s2中。 4)不断重复2)3)直到s1为空。 5)从s2弹出结点并打印 为什么是这样做:我们知道,没棵子树的头节点都是最先从s1中弹出,然后把该结点的孩子结点按照从左到右的顺序压入s1,那么从s1弹出的顺序就是现右再左,所以从s1中弹出的顺序就是中,右,左。s2重新输出就是s1弹出顺序的逆序。所以s2从栈顶到栈底的顺序就是左,右,中。