用非递归方法遍历二叉树(附Morris算法)

不使用递归遍历二叉树有几种方法:迭代,线索二叉树和Morris算法(通过临时转换二叉树变成一个类似链表的结构)。下面是迭代方法和递归的对比,后面单独列出Morris算法的实现。

迭代方法和递归的对比实现:

import java.util.Stack;
/**
 * 
 * Using recursive & iterative(ie. non-recursive) methods to traverse binary tree in 
 * inorder, preorder and postorder
 * 
 * @author ljs 
 * 2011-05-25
 * 
 *
 */
public class BinTree {
	static class Node{
		int val;
		Node left;
		Node right;
		boolean visited;
		public Node(int val){
			this.val = val;
		}
		public String toString(){
			return String.valueOf(val);
		}
	}
	public static void recursiveInOrderTraverse(Node root){
		if(root == null)return;
		
		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算法的实现:

public static void morrisInOrder(Node node){
	 
		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;
				}				
			}
		}
	}
	

posted @ 2011-06-05 22:26  ljsspace  阅读(544)  评论(2编辑  收藏  举报