Morris遍历-如何用空间复杂度O(1)来遍历二叉树

  • Post author:
  • Post category:其他


参照和学习:


https://www.cnblogs.com/AnnieKim/archive/2013/06/15/morristraversal.html


解决的问题

:如何使用空间复杂度O(1),来遍历二叉树。

我们通常的办法:是递归或者利用栈的迭代,空间复杂度都为O(logN),虽然已经很完美,但是还有更加美丽和充满艺术感的Morris。


Morris解法

:首先要面临的问题是,O(1)的空间,遍历的时候怎么回去(常规方法,是利用栈,和递归存储先前信息的能力),我们所知道的二叉树的叶节点,都有两个空间浪费了,指向NULL。Morris就把这些空间给利用了起来,达到回去的效果。


流程

:我们记来到的当前节点为

cur

。大致分为两步,第二步再分两步,一共三步。

(1)如果

cur

无左孩子,则

cur

向右移动。即(

cur = cur.right

(2)如果

cur

有左孩子,则找到

cur

左子树上最右的节点,记为

mostRigth

1、如果

mostRight

的右指针指向NULL,则让其指向

cur

,然后

cur

向左移动。即(

cur = cur.left

2、如果

mostRight

的右指针指向

cur

,则让其指向NULL,然后

cur

向右移动。即(

cur = cur.right

代码:

package advanced_class_03;

public class Code_01_MorrisTraversal {

	
	
	public static void process(Node head) {
		if(head == null) {
			return;
		}
		
		// 1
		//System.out.println(head.value);
		
		
		process(head.left);
		
		// 2
		//System.out.println(head.value);
		
		
		process(head.right);
		
		// 3
		//System.out.println(head.value);
	}
	
	
	public static class Node {
		public int value;
		Node left;
		Node right;

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

	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) {  // 如果cur有左孩子
				while (mostRight.right != null && mostRight.right != cur) { // 找到cur左子树最右的节点
					mostRight = mostRight.right;
				}
				if (mostRight.right == null) {  // 如果mostRight的右指针为空,则让其指向cur,然后cur向左移动
					mostRight.right = cur;
					cur = cur.left;
					continue;
				} else {   
					mostRight.right = null;  // 恢复mostRight的右指针
				}
			}
			System.out.print(cur.value + " "); // 打印当前节点
			cur = cur.right;     // 注意代码的逻辑性,如果cur没有左孩子和mostRight的右指针不为空,都向右走。
		}
		System.out.println();
	}

	public static void morrisPre(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;
					System.out.print(cur.value + " ");
					cur = cur.left;
					continue;
				} else {
					mostRight.right = null;
				}
			} else {
				System.out.print(cur.value + " ");
			}
			cur = cur.right;
		}
		System.out.println();
	}

	public static void morrisPos(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;
					printEdge(cur.left);
				}
			}
			cur = cur.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);
	}

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

	// for test -- print tree
	public static void printTree(Node head) {
		System.out.println("Binary Tree:");
		printInOrder(head, 0, "H", 17);
		System.out.println();
	}

	public static void printInOrder(Node head, int height, String to, int len) {
		if (head == null) {
			return;
		}
		printInOrder(head.right, height + 1, "v", len);
		String val = to + head.value + to;
		int lenM = val.length();
		int lenL = (len - lenM) / 2;
		int lenR = len - lenM - lenL;
		val = getSpace(lenL) + val + getSpace(lenR);
		System.out.println(getSpace(height * len) + val);
		printInOrder(head.left, height + 1, "^", len);
	}

	public static String getSpace(int num) {
		String space = " ";
		StringBuffer buf = new StringBuffer("");
		for (int i = 0; i < num; i++) {
			buf.append(space);
		}
		return buf.toString();
	}

	public static void main(String[] args) {
		Node head = new Node(4);
		head.left = new Node(2);
		head.right = new Node(6);
		head.left.left = new Node(1);
		head.left.right = new Node(3);
		head.right.left = new Node(5);
		head.right.right = new Node(7);
		printTree(head);
		morrisIn(head);
		morrisPre(head);
		morrisPos(head);
		printTree(head);

	}

}



版权声明:本文为qq_39598086原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。