用非递归方法遍历二叉树(附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; } } } }