不使用递归遍历二叉树有几种方法:迭代,线索二叉树和Morris算法(通过临时转换二叉树变成一个类似链表的结构)。下面是迭代方法和递归的对比,后面单独列出Morris算法的实现。
迭代方法和递归的对比实现:
recursiveInOrderTraverse(root.left);
System.out.format(" %d", root.val);
recursiveInOrderTraverse(root.right);
}
@SuppressWarnings("unchecked")
public static void iterativeInOrderTraverse(Node root){
Stack stack = new Stack();
Node node = root;
while(true){
if(node != null){
stack.push(node);
node = node.left;
}else{
if(!stack.isEmpty()){
node = (Node)stack.pop();
System.out.format(" %d", node.val); //visit
node = node.right;
}else{
break;
}
}
}
}
public static void recursivePreOrderTraverse(Node root){
if(root == null)return;
System.out.format(" %d", root.val);
recursivePreOrderTraverse(root.left);
recursivePreOrderTraverse(root.right);
}
@SuppressWarnings("unchecked")
public static void iterativePreOrderTraverse1(Node root){
if(root == null)return;
Stack stack = new Stack();
Node node = root;
while(true){
System.out.format(" %d", node.val); //visit
if(node.right != null)
stack.push(node.right);
if(node.left != null)
stack.push(node.left);
if(!stack.isEmpty())
node = (Node)stack.pop();
else
break;
}
}
@SuppressWarnings("unchecked")
public static void iterativePreOrderTraverse2(Node root){
if(root == null)return;
Stack stack = new Stack();
Node node = root;
while(true){
if(node != null){
System.out.format(" %d", node.val); //visit
stack.push(node);
node = node.left;
}else{
if(!stack.isEmpty()){
node = (Node)stack.pop();
node = node.right;
}else{
break;
}
}
}
}
public static void recursivePostOrderTraverse(Node root){
if(root == null)return;
recursivePostOrderTraverse(root.left);
recursivePostOrderTraverse(root.right);
System.out.format(" %d", root.val);
}
@SuppressWarnings("unchecked")
public static void iterativePostOrderTraverse(Node root){
if(root == null)return;
Stack stack = new Stack();
Node node = root;
Node lastNode = null;
while(true){
if(node != null){
stack.push(node);
node = node.left;
}else{
if(!stack.isEmpty()){
node = (Node)stack.peek();
node = node.right;
if(node == null || node == lastNode){
node = (Node)stack.pop();
System.out.format(" %d", node.val); //visit
lastNode = node;
if(!stack.isEmpty()){
node = (Node)stack.peek();
node = node.right;
if(node == lastNode){
//set as null to let it execute the second branch in while
node = null;
}
}else{
break;
}
}
}else{
break;
}
}
}
}
public static void main(String[] args){
/*
14
10 25
2 12 20 31
13 19 21 29
*/
Node n14 = new Node(14);
Node n10 = new Node(10);
Node n25 = new Node(25);
Node n2 = new Node(2);
Node n12 = new Node(12);
Node n13 = new Node(13);
Node n20 = new Node(20);
Node n21 = new Node(21);
Node n19 = new Node(19);
Node n31 = new Node(31);
Node n29 = new Node(29);
n14.left = n10;
n14.right = n25;
n10.left = n2;
n10.right = n12;
n12.right = n13;
n25.left = n20;
n25.right = n31;
n20.left = n19;
n20.right = n21;
n31.left = n29;
System.out.format("preorder(recursive):%n");
recursivePreOrderTraverse(n14);
System.out.println();
System.out.format("preorder(iterative 1):%n");
iterativePreOrderTraverse1(n14);
System.out.println();
System.out.format("preorder(iterative 2):%n");
iterativePreOrderTraverse2(n14);
System.out.println();
System.out.format("************************%n");
System.out.format("postorder(recursive):%n");
recursivePostOrderTraverse(n14);
System.out.println();
System.out.format("postorder(iterative):%n");
iterativePostOrderTraverse(n14);
System.out.println();
System.out.format("************************%n");
System.out.format("inorder(recursive):%n");
recursiveInOrderTraverse(n14);
System.out.println();
System.out.format("inorder(iterative):%n");
iterativeInOrderTraverse(n14);
System.out.println();
}
}
测试输出:
preorder(recursive):
14 10 2 12 13 25 20 19 21 31 29
preorder(iterative 1):
14 10 2 12 13 25 20 19 21 31 29
preorder(iterative 2):
14 10 2 12 13 25 20 19 21 31 29
************************
postorder(recursive):
2 13 12 10 19 21 20 29 31 25 14
postorder(iterative):
2 13 12 10 19 21 20 29 31 25 14
************************
inorder(recursive):
2 10 12 13 14 19 20 21 25 29 31
inorder(iterative):
2 10 12 13 14 19 20 21 25 29 31
Morris算法的实现:
Node p = node;
Node tmp = null;
while(p != null){
if(p.left == null){
System.out.format(" %d", p.val);
p = p.right;
}else{
//the left side(including the fake case)
tmp = p.left;
//find the p's predecessor
while(tmp.right != null
&& tmp.right != p) {
tmp = tmp.right;
}
if(tmp.right == null){ //transform
//the tmp is the leaf
//establish a fake right node
tmp.right = p;
//next root
p = p.left;
}else{ //restore the fake link: tmp.right == p
System.out.format(" %d", p.val);
tmp.right = null;
p = p.right;
}
}
}
}