java version
import java.util.ArrayList;
public class Learn {
public static void main(String[] args) {
TreeNode root = new TreeNode(5);
root.left = new TreeNode(2);
root.left.left = new TreeNode(1);
root.left.right = new TreeNode(4);
root.left.right.left = new TreeNode(3);
root.right = new TreeNode(6);
root.right.right = new TreeNode(7);
BinaryTree tree = new BinaryTree(root);
tree.postOrderMorris(tree.root);
for(int a : tree.postorder) System.out.println(a);
}
}
class TreeNode {
int val;
TreeNode left, right;
public TreeNode(int x) {
val = x;
left = right = null;
}
}
class BinaryTree {
TreeNode root;
ArrayList<Integer> preorder, inorder, postorder;
public BinaryTree(TreeNode root) {
this.root = root;
preorder = new ArrayList<>();
inorder = new ArrayList<>();
postorder = new ArrayList<>();
}
//Recursion
//Time: O(n)
//Space: O(n)
public void preOrderRecursion(TreeNode root) {
if(root == null) return;
preorder.add(root.val);
preOrderRecursion(root.left);
preOrderRecursion(root.right);
return;
}
public void inOrderRecursion(TreeNode root) {
if(root == null) return;
inOrderRecursion(root.left);
inorder.add(root.val);
inOrderRecursion(root.right);
return;
}
public void postOrderRecursion(TreeNode root) {
if(root == null) return;
postOrderRecursion(root.left);
postOrderRecursion(root.right);
postorder.add(root.val);
return;
}
//Morris Traversal
//Time: O(n)
//Space: O(1)
public void preOrderMorris(TreeNode root) {
while(root != null) {
if(root.left != null) {
//if has left subtree
TreeNode lmr = getLeftMostRight(root);
if(lmr.right == root) {
//currently at root, and its left has been traversed
//return from this link
lmr.right = null; //remove link
// preorder.add(root.val);
root = root.right;
} else {
//make link
lmr.right = root;
preorder.add(root.val);
root = root.left;
}
} else {
//if left subtree is empty
preorder.add(root.val);
root = root.right;
}
}
return;
}
public void inOrderMorris(TreeNode root) {
while(root != null) {
if(root.left != null) {
//if has left subtree
TreeNode lmr = getLeftMostRight(root);
if(lmr.right == root) {
//currently at root, and its left has been traversed
//return from this link
lmr.right = null; //remove link
inorder.add(root.val);
root = root.right;
} else {
//make link
lmr.right = root;
root = root.left;
}
} else {
//if left subtree is empty
inorder.add(root.val);
root = root.right;
}
}
return;
}
//visit only occurs when goes down right
//向右下方斜着一条一条访问
public void postOrderMorris(TreeNode root) {
TreeNode node = root;
while(node != null) {
if(node.left != null) {
//if has left subtree
TreeNode lmr = getLeftMostRight(node);
if(lmr.right == node) {
//currently at node, and its left has been traversed
//return from this link
lmr.right = null; //this link only serves for go back, till this point, its mission is completed
visitReversedEdgeDownRight(node.left);
node = node.right;
} else {
//make link
lmr.right = node;
node = node.left;
}
} else {
//if left subtree is empty
node = node.right;
}
}
visitReversedEdgeDownRight(root); //最后一条右下斜访问,因为每次访问都从左子过来,root没有父节点能过来,所以单独拉出来
return;
}
//only reverse the edge which goes down right
//return the tail node in the original tree
public TreeNode reverseRight(TreeNode root) {
TreeNode prev = root, cur = root.right;
prev.right = null;
while(cur != null) {
TreeNode temp = cur.right;
cur.right = prev;
prev = cur;
cur = temp;
}
return prev;
}
public void visitReversedEdgeDownRight(TreeNode root) {
// if(root == null) return;
TreeNode tail = reverseRight(root);
TreeNode node = tail;
while(node != null) {
postorder.add(node.val);
node = node.right;
}
reverseRight(tail); //recover the original right edge
return;
}
//requires that root has left tree, root.left is not null
public TreeNode getLeftMostRight(TreeNode root) {
TreeNode node = root.left;
while(node.right != null && node.right != root) node = node.right;
return node;
}
}