- [1 Morriséå](#1)
* [1.1 Morriséåç®ç](#11)
+ [1.1.1 ç®æ³æµç¨](#111)
+ [1.1.2 æ¶é´å¤æåº¦ä¼°è®¡](#112)
* [1.2 Morriséåçåºç¨](#12)
* [1.3 Morriséå为æä¼è§£çæ
æ¯](#13)
1 Morriséå
1.1 Morriséåç®ç
å¨äºåæ çéåä¸ï¼æé彿¹å¼éååééå½éå两ç§ãä¸ç®¡åªç§æ¹å¼ï¼æ¶é´å¤æåº¦ä¸ºO(N)ï¼ç©ºé´å¤æåº¦ä¸ºO(h),h为æ çé«åº¦ãMorriséåå¯ä»¥å¨æ¶é´å¤æåº¦O(N),空é´å¤æåº¦O(1)å®ç°äºåæ çéå
1.1.1 ç®æ³æµç¨
ä»ä¸ä¸ªæ ç头ç»ç¹curå¼å§ï¼
1ãcurçå·¦æ 为nullï¼cur = cur.right
2ãcuræå·¦æ ï¼æ¾å°å·¦æ çæå³çèç¹mostRight
- mostRightçå³å©åæånullï¼è®©mostRigth.right = cur;cur = cur.left
- mostRightçå³å©åæåå½åèç¹curï¼è®©mostRigth.right = null;cur = cur.rigth
- cur为nullçæ¶åï¼æ´ä¸ªæµç¨ç»æ
curç»è¿çå个èç¹ï¼ç§°ä¸ºMorrisåºï¼ä¾å¦å¦ä¸çæ ç»æï¼
```
graph TD
1-->2
1-->3
2-->4
2-->5
3-->6
3-->7
```
curç»è¿çè·¯å¾ä¹å°±æ¯Morrisåºä¸ºï¼1ï¼2ï¼4ï¼2ï¼5ï¼1ï¼3ï¼6ï¼3ï¼7
å¯ä»¥åç°ï¼åªè¦å½åèç¹æå·¦å©åï¼å½åèç¹ä¼æ¥å°ä¸¤æ¬¡ãå½å·¦æ æå³èç¹çå³å©åæånullï¼å¯ä»¥å¤å®ç¬¬ä¸æ¬¡æ¥å°curèç¹ï¼ä¸ä¸æ¬¡æ¥å°curå°±æ¯åç°å·¦æ çæå³èç¹æåçæ¯èªå·±ï¼è¯´æç¬¬äºæ¬¡æ¥å°curèç¹
å¨Morriséåçè¿ç¨ä¸ï¼ç¬¬ä¸æ¬¡å°è¾¾curå°±æå°ï¼åªä¼æ¥cur䏿¬¡çèç¹ä¹æå°ï¼å°±æ¯æ çå
åºéåï¼ç¬¬äºæ¬¡å°è¾¾ï¼åªä¼æ¥å°cur䏿¬¡çèç¹ä¹æå°ï¼æå°ä¸ºä¸åºãç¬¬äºæ¬¡æ¥å°curèç¹çæ¶åéåºæå°curå·¦æ çå³è¾¹çï¼æåéåºæå°æ´é¢æ çå³è¾¹çï¼éåºæå°å³è¾¹çä¸å¯ä»¥ä½¿ç¨é¢å¤çç»æï¼å 为æä»¬è¦æ±ç©ºé´å¤æåº¦ä¸ºO(1)ï¼å¯ä»¥ä½¿ç¨ç¿»è½¬é¾è¡¨
翻转é¾è¡¨ï¼ä¾å¦a->b->c->d->nullãå¯ä»¥è®©a-null,b->a,c->b,d->cå³å¯ãæå°å®ä¹åæé¾è¡¨åç¿»è½¬è¿æ¥
1.1.2 æ¶é´å¤æåº¦ä¼°è®¡
curæ¥å°èç¹çæ¶é´å¤æåº¦ä¸ºO(N),æ¯ä¸ªcuréåå·¦æ æå³è¾¹çç代价æå¤ä¸ºO(2N),æä»¥æ´ä¸ªéåè¿ç¨ä¸ºO(N)ï¼æ´ä¸ªéåè¿ç¨åªç¨å°å°æéçå 个åéï¼å
¶ä»ä½¿ç¨ç齿¯æ æ¬èº«çæéå
³ç³»ã
```Java
public class Code01_MorrisTraversal {
public static class Node {
public int value;
Node left;
Node right;
public Node(int data) {
this.value = data;
}
}
// morriséå
public static void morris(Node head) {
if (head == null) {
return;
}
Node cur = head;
Node mostRight = null;
while (cur != null) {
// curææ²¡æå·¦æ
mostRight = cur.left;
if (mostRight != null) { // æå·¦æ çæ
åµä¸
// æ¾å°curå·¦æ ä¸ï¼çå®çæå³
while (mostRight.right != null && mostRight.right != cur) {
mostRight = mostRight.right;
}
// ä»whileä¸åºæ¥ï¼mostRightä¸å®æ¯curå·¦æ ä¸çæå³èç¹
// mostRight妿çäºnullï¼è¯´æç¬¬ä¸æ¬¡æ¥å°èªå·±
if (mostRight.right == null) {
mostRight.right = cur;
cur = cur.left;
continue;
// å¦åç¬¬äºæ¬¡æ¥å°èªå·±ï¼æå³çmostRight.right = cur
} else { // mostRight.right != null -> mostRight.right == cur
mostRight.right = null;
}
}
cur = cur.right;
}
}
// Morrisä¸åºéå
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) {
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.print(cur.value + " ");
cur = cur.right;
}
System.out.println();
}
// Morriså
åºéå
public static void morrisPre(Node head) {
if (head == null) {
return;
}
// cur
Node cur1 = head;
// mostRight
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.print(cur1.value + " ");
cur1 = cur1.left;
continue;
} else {
cur2.right = null;
}
} else {
System.out.print(cur1.value + " ");
}
cur1 = cur1.right;
}
System.out.println();
}
// Morrisååºéå
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;
}
// whileç»æçæ¶åï¼æ´é¢æ çå³è¾¹çåæ ·ç翻转æå°ä¸æ¬¡
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();
}
// å¨Morriséåçåºç¡ä¸ï¼å¤æä¸é¢æ æ¯ä¸æ¯ä¸é¢æç´¢äºåæ
// æç´¢äºåæ æ¯å·¦æ¯èªå·±å°ï¼å³æ¯èªå·±å¤§
// ä¸é¢æ ä¸åºéåï¼å¼ä¸ç´å¨éå¢ï¼å°±æ¯æç´¢äºåæ
public static boolean isBST(Node head) {
if (head == null) {
return true;
}
Node cur = head;
Node mostRight = null;
Integer pre = null;
boolean ans = true;
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) {
ans = false;
}
pre = cur.value;
cur = cur.right;
}
return ans;
}
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);
}
}
```
1.2 Morriséåçåºç¨
å¨ä¸é¢äºåæ ä¸ï¼æ±è¯¥äºåæ çæå°é«åº¦ãæå°é«åº¦æçæ¯ï¼ææå¶åèç¹è·ç¦»å¤´èç¹çæå°å¼
> äºåæ é彿±è§£ï¼æ±å·¦æ çæå°é«åº¦å 1å峿 çæå°é«åº¦å 1ï¼æ¯è¾
> Morriséåæ±è§£ï¼æ¯å°è¾¾ä¸ä¸ªcurçæ¶åï¼è®°å½é«åº¦ãæ¯å°è¾¾ä¸ä¸ªcurçæ¶å夿curæ¯å¦ä¸ºå¶åèç¹ï¼æ´æ°å
¨å±æå°å¼ãæåçä¸ä¸æåä¸ä¸ªèç¹çé«åº¦åå
¨å±æå°é«åº¦å¯¹æ¯ï¼åæå°é«åº¦
```Java
public class Code05_MinHeight {
public static class Node {
public int val;
public Node left;
public Node right;
public Node(int x) {
val = x;
}
}
// è§£æ³1 è¿ç¨äºåæ çéå½
public static int minHeight1(Node head) {
if (head == null) {
return 0;
}
return p(head);
}
public static int p(Node x) {
if (x.left == null && x.right == null) {
return 1;
}
// å·¦å³åæ èµ·ç æä¸ä¸ªä¸ä¸ºç©º
int leftH = Integer.MAX_VALUE;
if (x.left != null) {
leftH = p(x.left);
}
int rightH = Integer.MAX_VALUE;
if (x.right != null) {
rightH = p(x.right);
}
return 1 + Math.min(leftH, rightH);
}
// è§£æ³2 æ ¹æ®morriséåæ¹å
public static int minHeight2(Node head) {
if (head == null) {
return 0;
}
Node cur = head;
Node mostRight = null;
int curLevel = 0;
int minHeight = Integer.MAX_VALUE;
while (cur != null) {
mostRight = cur.left;
if (mostRight != null) {
int rightBoardSize = 1;
while (mostRight.right != null && mostRight.right != cur) {
rightBoardSize++;
mostRight = mostRight.right;
}
if (mostRight.right == null) { // ç¬¬ä¸æ¬¡å°è¾¾
curLevel++;
mostRight.right = cur;
cur = cur.left;
continue;
} else { // ç¬¬äºæ¬¡å°è¾¾
if (mostRight.left == null) {
minHeight = Math.min(minHeight, curLevel);
}
curLevel -= rightBoardSize;
mostRight.right = null;
}
} else { // åªæä¸æ¬¡å°è¾¾
curLevel++;
}
cur = cur.right;
}
int finalRight = 1;
cur = head;
while (cur.right != null) {
finalRight++;
cur = cur.right;
}
if (cur.left == null && cur.right == null) {
minHeight = Math.min(minHeight, finalRight);
}
return minHeight;
}
// for test
public static Node generateRandomBST(int maxLevel, int maxValue) {
return generate(1, maxLevel, maxValue);
}
// for test
public static Node generate(int level, int maxLevel, int maxValue) {
if (level > maxLevel || Math.random() < 0.5) {
return null;
}
Node head = new Node((int) (Math.random() * maxValue));
head.left = generate(level + 1, maxLevel, maxValue);
head.right = generate(level + 1, maxLevel, maxValue);
return head;
}
public static void main(String[] args) {
int treeLevel = 7;
int nodeMaxValue = 5;
int testTimes = 100000;
System.out.println("test begin");
for (int i = 0; i < testTimes; i++) {
Node head = generateRandomBST(treeLevel, nodeMaxValue);
int ans1 = minHeight1(head);
int ans2 = minHeight2(head);
if (ans1 != ans2) {
System.out.println("Oops!");
}
}
System.out.println("test finish!");
}
}
```
1.3 Morriséå为æä¼è§£çæ
æ¯
> 妿æä»¬ç®æ³æµç¨è®¾è®¡æï¼æ¯æ¥å°ä¸ä¸ªèç¹ï¼éè¦å·¦å³åæ çä¿¡æ¯è¿è¡æ´åï¼é£ä¹æ æ³ä½¿ç¨Morriséåãè¯¥ç§æ
åµç空é´å¤æåº¦ä¹ä¸å®ä¸æ¯O(1)ç
> å¦æç®æ³æµç¨æ¯ï¼å½åèç¹ä½¿ç¨å®å·¦æ æè
峿 çä¿¡æ¯åï¼æ éæ´åï¼é£ä¹å¯ä»¥ä½¿ç¨Morriséå
> Morriséåå±äºæ¯è¾å¤æçé®é¢