Morris遍历
Morris遍历法能以O(1)的空间复杂度和O(n)的时间复杂度实现二叉树的三种遍历,其中不使用栈或额外空间
常用的二叉树递归遍历中,要回到节点三次
public static void process(Node head){
if(head==null)
return;
//先序遍历
process(head.left);
//中序遍历
process(head.right);
//后序遍历
}
而在Morris遍历中,有左子树的节点来到两次,没有的仅一次。通过记录左子树的mostRight节点指向谁来判断来到第几次
public static void morris(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) { //2找到左子树的最右节点
cur2 = cur2.right;
}
if (cur2.right == null) { //2.1最右节点的右指针指向空,即第一次来到节点
cur2.right = cur1;
cur1 = cur1.left;
continue;
} else { //2.2最右节点的右指针指向cur1,即第二次来到节点
cur2.right = null;
}
}
//System.out.print(cur1.value + " ");
cur1 = cur1.right; //1节点向右移动
}
}
先序实现:只打印第一次来到的节点
中序实现:能来到两次的节点第二次打印,不能的直接打印
后序实现:对能来到两次的节点,逆序打印其左子树的右边界
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;
}
注意:Morris遍历只能解决回到节点第二次之内的二叉树问题