morris遍历的优点在于节省空间,因为不需要递归。
public class MorrisTraversal {
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);
morris(head);
morris2(head);
morrisPre(head);
morrisMiddle(head);
morrisPos(head);
}
public static class Node{
public int value;
Node left;
Node right;
public Node(int data){
this.value = data;
}
}
public static void morris(Node head){
if(head == null){
return ;
}
Node cur = head;
Node mostRight = null;
boolean isRighNull = true;
while(cur != null){
System.out.print(cur.value+" ");
if(cur.left == null){ // 如果cur没有左孩子,cur向右移动
cur = cur.right;
}else{
mostRight = cur.left;
isRighNull = true;
while (mostRight.right != null) {
if(mostRight.right == cur){
isRighNull = false;
break;
}
mostRight = mostRight.right;
}
if (isRighNull) {
mostRight.right = cur;
cur = cur.left;
}else{
mostRight.right = null;
cur = cur.right;
}
}
}
System.out.println();
}
public static void morris2(Node head){
if(head == null){
return ;
}
Node cur = head;
Node mostRight = null;
while(cur != null){
System.out.print(cur.value+" ");
mostRight = cur.left;
if(mostRight != null){// 如果cur没有左孩子,cur向右移动
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;
}
}
cur = cur.right;
}
System.out.println();
}
/*
* 先序遍历
* 1.如果当前节点没有左节点,就打印当前节点的值
* 2.如果当前节点有左节点,第一次到达该节点时,就打印此节点
* */
public static void morrisPre(Node head){
if(head == null){
return ;
}
Node cur = head;
Node mostRight = null;
while(cur != null){
//System.out.print(cur.value+" ");
mostRight = cur.left;
if(mostRight != null){// 如果cur没有左孩子,cur向右移动
while (mostRight.right != null && mostRight.right != cur){
mostRight = mostRight.right;
}
if(mostRight.right == null){
System.out.print(cur.value+" ");
mostRight.right = cur;
cur = cur.left;
continue;
}else{
mostRight.right = null;
}
}else{
System.out.print(cur.value+" ");
}
cur = cur.right;
}
System.out.println();
}
/*
* 中序遍历
* 1.如果当前节点没有左节点,就打印当前节点的值
* 2.如果当前节点有左节点,第二次到达该节点时,就打印此节点
* */
public static void morrisMiddle(Node head){
if(head == null){
return ;
}
Node cur = head;
Node mostRight = null;
while(cur != null){
//System.out.print(cur.value+" ");
mostRight = cur.left;
if(mostRight != null){// 如果cur没有左孩子,cur向右移动
while (mostRight.right != null && mostRight.right != cur){
mostRight = mostRight.right;
}
if(mostRight.right == null){
mostRight.right = cur;
cur = cur.left;
continue;
}else{
System.out.print(cur.value+" ");
mostRight.right = null;
}
}else{
System.out.print(cur.value+" ");
}
cur = cur.right;
}
System.out.println();
}
/*
* 后序遍历
* 1.如果当前节点有左节点,第二次到达该节点时,逆序打印该节点的左节点的右边界
* 2.最后打印整棵树的右边界
* */
public static void morrisPos(Node head){
if(head == null){
return ;
}
Node cur = head;
Node mostRight = null;
while(cur != null){
//System.out.print(cur.value+" ");
mostRight = cur.left;
if(mostRight != null){// 如果cur没有左孩子,cur向右移动
while (mostRight.right != null && mostRight.right != cur){
mostRight = mostRight.right;
}
if(mostRight.right == null){
mostRight.right = cur;
cur = cur.left;
continue;
}else{
//System.out.print(cur.value+" ");
mostRight.right = null;
printEdte(cur.left); // 第二次到达该节点时,逆序打印该节点的左节点的右边界
}
}
cur = cur.right;
}
printEdte(head);
System.out.println();
}
public static void printEdte(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;
}
}