Morris Traversal -Preorder & Inorder & Postorder

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;
    }
}
已标记关键词 清除标记
相关推荐
&lt;p&gt; &lt;b&gt;&lt;span style=&quot;font-size:14px;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-size:14px;background-color:#FFE500;&quot;&gt;【Java面试宝典】&lt;/span&gt;&lt;/b&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;1、68讲视频课,500道大厂Java常见面试题+100个Java面试技巧与答题公式+10万字核心知识解析+授课老师1对1面试指导+无限次回放&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;2、这门课程基于胡书敏老师8年Java面试经验,调研近百家互联网公司及面试官的问题打造而成,从筛选简历和面试官角度,给出能帮助候选人能面试成功的面试技巧。&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;3、通过学习这门课程,你能系统掌握Java核心、数据库、Java框架、分布式组件、Java简历准备、面试实战技巧等面试必考知识点。&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;4、知识点+项目经验案例,每一个都能做为面试的作品展现。&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;5、本课程已经在线下的培训课程中经过实际检验,老师每次培训结束后,都能帮助同学们运用面试技巧,成功找到更好的工作。&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;font-size:14px;background-color:#FFE500;&quot;&gt;&lt;b&gt;【超人气讲师】&lt;/b&gt;&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;胡书敏 | 10年大厂工作经验,8年Java面试官经验,5年线下Java职业培训经验,5年架构师经验&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;font-size:14px;background-color:#FFE500;&quot;&gt;&lt;b&gt;【报名须知】&lt;/b&gt;&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;上课模式是什么?&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;课程采取录播模式,课程永久有效,可无限次观看&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;font-size:14px;background-color:#FFE500;&quot;&gt;&lt;strong&gt;如何开始学习?&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;PC端:报名成功后可以直接进入课程学习&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;font-size:14px;&quot;&gt;移动端:&lt;span style=&quot;font-family:Helvetica;font-size:14px;background-color:#FFFFFF;&quot;&gt;CSDN 学院APP(注意不是CSDN APP哦)&lt;/span&gt;&lt;/span&gt; &lt;/p&gt;
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页