Morris遍历是一种时间复杂度O(n)的二叉树遍历。
Morris遍历与递归版本的二叉树遍历的关系(或者相似之处),如果一个节点有左子树那么Morris遍历可以回到左子树两次(递归方法是3次),Morris模拟了递归的过程。对于没有左子树的节点只会到达依一次。
Morris遍历(先序)的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
   |    public static void morrisPre(Node head) { 	if (head == null) { 		return; 	} 	Node cur1 = head; 	Node cur2 = null; 	while (cur1 != null) { 		cur2 = cur1.left; 		if (cur2 != null) { 			while (cur2.right != null && cur2.right != cur1) { 				cur2 = cur2.right; 			} 			if (cur2.right == null) { 				cur2.right = cur1; 				System.out.print(cur1.value + " "); 				cur1 = cur1.left; 				continue; 			} else { 				cur2.right = null; 			} 		} else { 			System.out.print(cur1.value + " "); 		} 		cur1 = cur1.right; 	} 	System.out.println(); }
  | 
 
Morris遍历(中序)的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
   |    public static void morrisIn(Node head) { 	if (head == null) { 		return; 	} 	Node cur = head; 	Node mostRight = null; 	while (cur != null) { 		mostRight = cur.left; 		if (mostRight != null) { 			while (mostRight.right != null && mostRight.right != cur) { 				mostRight = mostRight.right; 			} 			if (mostRight.right == null) { 				mostRight.right = cur; 				cur = cur.left; 				continue; 			} else { 				mostRight.right = null; 			} 		} 		System.out.print(cur.value + " "); 		cur = cur.right; 	} 	System.out.println(); }
  | 
 
注:后序遍历有点麻烦,因为Morris遍历最多只能回到一个节点两次并不会回到第三次。采用下面的方法打印后序遍历:所有会回到两次的节点,在它第二次回到的时候逆序打印它的左子树右边界,打印完后,单独打印整棵树的右边界,这就后序遍历。
只关注能来到两次的节点。
Morris遍历(后序)的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
   |    public static void morrisPos(Node head) { 	if (head == null) { 		return; 	} 	Node cur1 = head; 	Node cur2 = null; 	while (cur1 != null) { 		cur2 = cur1.left; 		if (cur2 != null) { 			while (cur2.right != null && cur2.right != cur1) { 				cur2 = cur2.right; 			} 			if (cur2.right == null) { 				cur2.right = cur1; 				cur1 = cur1.left; 				continue; 			} else { 				cur2.right = null; 				printEdge(cur1.left); 			} 		} 		cur1 = cur1.right; 	} 	printEdge(head); 	System.out.println(); }
     public static void printEdge(Node head) { 	Node tail = reverseEdge(head); 	Node cur = tail; 	while (cur != null) { 		System.out.print(cur.value + " "); 		cur = cur.right; 	} 	reverseEdge(tail); }
  |