Morris遍历二叉树

Morris遍历的实质就是避免用栈结构,而是让下层到上层有指针,具体是通过让底层节点指向null的空闲指针指回上层的某个节点,从而完成下层到上层的移动。

中序遍历的过程如下

1.假设当前子树的头节点为h,让h的左子树中最右节点的right指针指向h,然后h的左子树继续步骤1的处理过程,直到遇到某一个节点没有左子树时记为node,进入步骤2。

2.从node开始通过每个节点的right指针进行移动,并依次打印,假设移动到的节点为cur。对每一个cur节点都判断cur节点的左子树中最右节点是否指向cur。

​ 1) .如果是,让cur节点的左子树中最右节点的right指针指向空,也就是把步骤1的调整后再逐渐调整回来,然后打印cur,继续通过cur的right指针移动到下一个节点,重复步骤2。

​ 2) .如果不是,以cur为头的子树重回步骤1执行。

先序遍历的实现就是Morris中序遍历的简单改写。中序遍历的打印时机放在了步骤2所描述的移动过程中,而先序遍历只要把打印时机放在步骤1发生的时候即可。步骤1发生的时候,正在处理以h为头的子树,并且是以h为头的子树首次进入调整过程,此时直接打印h,就可以做到先根打印。

后序遍历的实现也是Morris中序遍历的改写,但过程更复杂,依次逆序打印所有节点的左子树的右边界,打印的时机放在步骤2的条件1)被触发的时候,也就是调回去的过程发生的时候。

public class Morris {
	public static class Node {
		public int value;
		public Node left;
		public Node right;

		public Node(int value) {
			this.value = value;
		}
	}

	public static void morrisIn(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;
				}
			}
			System.out.println(cur1.value);
			cur1 = cur1.right;
		}
	}

	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.println(cur1.value);
					cur1 = cur1.left;
					continue;
				} else {
					cur2.right = null;
				}
			} else {
				System.out.println(cur1.value);
			}
			System.out.println(cur1.value);
			cur1 = cur1.right;
		}
	}

	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);
	}

	private 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);
	}

	private static Node reverseEdge(Node from) {
		Node pre = null;
		Node next = null;
		while (from != null) {
			next = from.right;
			from.right = pre;
			pre = from;
			from = next;
		}
		return pre;
	}
}

猜你喜欢

转载自blog.csdn.net/gkq_tt/article/details/86515670