Morris遍历
(实现Morris遍历并利用Morris实现前中后序遍历,时间复杂度O(N),空间复杂度O(1))
算法思想:
当前节点cur,一开始cur来到树的头节点。
1>cur==null时,停。
2>cur无左树,cur = cur.right
3>cur有左树,找到左树最右节点,mostRight
1.若mostRight的右指针指向null
mostRight.right=cur , cur=cur.left
2.若mostRight的右指针指向cur
mostRight.right=null , cur=cur.right
Morris实现
public class Morris {
// 树节点
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;
while(cur !=null) {
// cur有没有左树
mostRight = cur.left;
// cur有左树
if(mostRight !=null) {
// 找到cur左树上,真实的最右节点
while(mostRight.right!=null&&mostRight.right!=cur) {
mostRight = mostRight.right;
}
// 从while中出来,mostRight一定是cur左树上的最右节点
if(mostRight.right==null) {
mostRight.right=cur;
cur = cur.left;
continue;
}else { // mostRight.right!=null
mostRight.right=null;
}
}
// cur无左树
cur =cur.right;
}
}
}
利用Morris先序遍历
// morris实现先序遍历
public static void morrisPreorder(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;
}
}else {
System.out.println(cur.value+" ");
}
cur =cur.right;
}
}
利用Morris中序遍历
// morris实现中序遍历
public static void morrisInorder(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.println(cur.value+" ");
cur =cur.right;
}
}
利用Morris后序遍历
// morris实现后序遍历
public static void morrisPostorder(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);
}
}
printEdge(head);
cur =cur.right;
}
}
// 输出反转后树的右边界,并将其反转回来
public static void printEdge(Node head) {
Node tail = reverseEdge(head);
Node cur = tail;
while(cur!=null) {
System.out.println(cur.value+" ");
}
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判断是否是搜索二叉树
搜索二叉树(又:二叉查找树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树:若它的左子树不空,则左树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树。搜索二叉树可以方便的查找树中的最大值或最小值。
// morris实现判断是否是二叉搜索树
public static boolean isBST(Node head) {
if(head ==null) {
return true;
}
Node cur = head;
Node mostRight = null;
Integer pre = 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;
}
}
if(pre!=null&&pre>=cur.value) {
return false;
}
pre = cur.value;
cur =cur.right;
}
return true;
}