leetcode 二叉树 先中后三种遍历的 迭代 Morris

迭代

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> ans=new ArrayList<Integer>();
        Stack<TreeNode> stk=new Stack<TreeNode>();
        while(root!=null||!stk.isEmpty()){
            while(root!=null){
                ans.add(root.val);
                stk.push(root);
                root=root.left;
            }
            root=stk.pop();
            root=root.right;
        }
        return ans;
    }
}

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> ans=new ArrayList<>();
        Deque<TreeNode> stk=new LinkedList<>();
        while(root!=null||!stk.isEmpty()){
            while(root!=null){
                stk.push(root);
                root=root.left;
            }
            root=stk.pop();
            ans.add(root.val);
            root=root.right;
        }
        return ans;
    }
}

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<Integer>();
        if (root == null) return ans;
        Deque<TreeNode> stk = new LinkedList<TreeNode>();
        TreeNode pre = null;
        while (root != null || !stk.isEmpty()) {
            while (root != null) {
                stk.push(root);
                root = root.left;
            }
            root = stk.pop();
            if (root.right == null || root.right == pre) {
                //第二次访问,或者是右子树为空的情况,记录答案,记录pre,置root为空
                ans.add(root.val);
                pre = root;
                root = null;
            } else {
                //第一次访问节点,将自己压回栈,然后进入右子树
                stk.push(root);
                root = root.right;
            }
        }
        return ans;
    }
}


Morris

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        while (root != null) {
            if (root.left != null) {
                TreeNode pre = root.left;
                while (pre.right != null && pre.right != root) pre = pre.right;
                if (pre.right == null) {
                    //第一次找到左子树的最右节点,先将自己加入ans,再挂上,相当于标记,然后进入左子树
                    res.add(root.val);
                    pre.right = root;
                    root = root.left;
                } else {
                    //第二次找到左子树的最右节点,此时本节点和左子树都访问完了,直接进入右子树
                    //pre.right = null;//把挂上去的再取下去,恢复树的结构,但是对答案不影响
                    root = root.right;
                }
            } else {
                //没有左子树,当然就不要先找了,直接将自己加入答案,然后进入右子树
                res.add(root.val);
                root = root.right;
            }
        }
        return res;
    }
}


class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        TreeNode predecessor = null;

        while (root != null) {
            if (root.left != null) {
                // predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
                predecessor = root.left;
                while (predecessor.right != null && predecessor.right != root) {
                    predecessor = predecessor.right;
                }
                
                // 让 predecessor 的右指针指向 root,继续遍历左子树
                if (predecessor.right == null) {
                    predecessor.right = root;
                    root = root.left;
                }
                // 说明左子树已经访问完了,我们需要断开链接
                else {
                    res.add(root.val);
                    predecessor.right = null;
                    root = root.right;
                }
            }
            // 如果没有左孩子,则直接访问右孩子
            else {
                res.add(root.val);
                root = root.right;
            }
        }
        return res;
    }
}

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        TreeNode rt=root;
        List<Integer> ans = new ArrayList<Integer>();
        if (root == null) return ans;

        while (root != null) {
            if (root.left != null) {
                TreeNode pre = root.left;
                while (pre.right != null && pre.right != root) pre=pre.right;
                if (pre.right == null) {
                    pre.right = root;
                    root = root.left;
                } else {
                    pre.right = null;//这条不能省略,因为后面访问斜的路径还要以它来判断终点
                    addPath(ans, root.left);
                    root = root.right;
                }
            }
            else {
                root = root.right;
            }
        }
        addPath(ans, rt);
        return ans;
    }

    访问一斜行,类似于adidas
    public void addPath(List<Integer> ans, TreeNode node) {
        int cnt = 0;
        while (node != null) {
            ++cnt;
            ans.add(node.val);
            node = node.right;
        }
        int l = ans.size() - cnt, r = ans.size() - 1;
        while (l < r) {
            int t = ans.get(l);
            ans.set(l, ans.get(r));
            ans.set(r, t);
            l++;
            r--;
        }
    }

    // public void addPath(List<Integer> ans, TreeNode node) {
    //     if(node==null)return ;
    //     addPath(ans,node.right);
    //     ans.add(node.val);
    // }

}

posted @ 2022-11-17 23:01  林动  阅读(14)  评论(0编辑  收藏  举报