前序遍历、中序遍历、后序遍历-morris

前序遍历

前序遍历:中 -> 左子树 -> 右子树

非递归的遍历-stack

public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (null == root) {
            return res;
        }
        LinkedList<TreeNode> stack = new LinkedList<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            res.add(node.val);
            if (null != node.right) {
                stack.push(node.right);
            }
            if (null != node.left) {
                stack.push(node.left);
            }
        }
        return res;
    }

morris

空间复杂度为O(1)

public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        if (root == null) {
            return res;
        }
        TreeNode cur = root;
        while (cur != null) {
            // 左子树不为null,优先处理
            if (null != cur.left) {
                TreeNode leftMaxRight = cur.left;
                while (leftMaxRight.right != null && leftMaxRight.right != cur) {
                    leftMaxRight = leftMaxRight.right;
                }
                // leftMaxRight为叶子结点,right==null表示 要续上;否则表示 已经处理完,要恢复
                if (leftMaxRight.right == null) {
                    res.add(cur.val);
                    // 续上 连接,指向中序排序下一个结点:leftMaxRight若为左子树,则right=parent; 若为右子树,则right = 所在树的root.root
                    leftMaxRight.right = cur;
                    cur = cur.left;
                    continue;
                } else {
                    // leftMaxRight为叶子结点,将续上的连接 恢复null值
                    leftMaxRight.right = null;
                }
            } else {
                // 1) 非叶子结点,左子树为null,直接添加cur,再处理其右子树
                // 2) 叶子结点,右子树 为 续上 的连接,指向中序排序下一个结点
                res.add(cur.val);
            }
            // 1)cur及其左子树 处理完后,处理右子树
            // 2)cur为叶子节点时,cur.right为 其 中序 遍历的 下一个节点
            cur = cur.right;
        }
        return res;
    }

遍历时续上的连接 如下所示,指向 中序遍历 的下一个结点,node5.right=node1, node4.right = node2
在这里插入图片描述
1: 5->1, 输出1,进入2
2: 4->2, 输出2,进入4
4: 输出4,进入2

2: 断开 4->2, 进入5
5:输出5,进入1

1: 断开5->1, 进入3
3: 6->3, 输出3,进入6
6: 输出6,进入3
3: 断开6->3, 进入7
7: 输出7
最终序列为:1、2、4、5、3、6、7

力扣上的题目:
https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/461821/er-cha-shu-de-qian-xu-bian-li-by-leetcode-solution/?company_slug=meituan

后序遍历

左子树 -> 右子树 -> root

morris

public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (null == root) {
            return res;
        }
        TreeNode cur = root;
        while (null != cur) {
            if (null != cur.left) {
                TreeNode leftMaxRight = cur.left;
                while (leftMaxRight.right != null && leftMaxRight.right != cur) {
                    leftMaxRight = leftMaxRight.right;
                }
                if (leftMaxRight.right == null) {
                    // 续上, 中序遍历的下一个结点
                    leftMaxRight.right = cur;
                    cur = cur.left;
                    continue;
                } else {
                    // 将续上的干掉
                    leftMaxRight.right = null;
                    // 叶子结点 在 第2次遍历到其parent时,才会处理
                    addNodeRight(res, cur.left);
                }
            } 
            cur = cur.right;
        }
        // 处理最后的右子树横线
        addNodeRight(res, root);
        return res;
    }
    // 处理node开始的右子树 线
    public void addNodeRight(List<Integer> res, TreeNode node) {
        int left = res.size();
        while (null != node) {
            res.add(node.val);
            node = node.right;
        }
        int right = res.size() - 1;
        // left为第一个插入位置,right为最后插入位置
        // 将left和right范围内 倒转
        while (left < right) {
            int tmp = res.get(left);
            res.set(left, res.get(right));
            res.set(right, tmp);
            left++;
            right--;
        }
    }

在这里插入图片描述
leetcode题目地址:https://leetcode.cn/problems/binary-tree-postorder-traversal/submissions/?company_slug=meituan

中序遍历-morris

参考前序遍历

public List<Integer> inorderTraversal(TreeNode root) {
       List<Integer> res = new ArrayList<Integer>();
        if (root == null) {
            return res;
        }
        TreeNode cur = root;
        while (cur != null) {
            if (null != cur.left) {
                TreeNode leftMaxRight = cur.left;
                while (leftMaxRight.right != null && leftMaxRight.right != cur) {
                    leftMaxRight = leftMaxRight.right;
                }
                if (leftMaxRight.right == null) {
                    leftMaxRight.right = cur;
                    cur = cur.left;
                    continue;
                } else {
                    // 前序遍历 cur在if放入 res;中序遍历在else里面加入
                    res.add(cur.val);
                    leftMaxRight.right = null;
                }
            } else {
                res.add(cur.val);
            }
            cur = cur.right;
        }
        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值