LeetCode 144. Binary Tree Preorder Traversal

问题描述

  • Given a binary tree, return the preorder traversal of its nodes’ values.
  • 地址

问题分析

  • 如何先序遍历左子树
  • 递归法
  • 非递归
    • 法1:教科书法
      稍微改变一下打印顺序,前序中序便通用
    • 法2:
      当某节点出栈时,便打印,然后将它的右孩子,左孩子(若不为空)压栈,注意先右后左
    • 法3 : 金手指法
      完全模拟递归时系统栈的状态,用一个类(指令)来表征当前节点是打印还是遍历。可以改变指令指令入栈顺序,来实现前序,中序,后序遍历

代码实现

  • 递归
    public void preorderTraversal(TreeNode root, List<Integer> res) {
        if (root == null) {
            return;
        }
        //根
        res.add(root.val);
        //递归先序遍历左子树
        preorderTraversal(root.left, res);
        //递归先序遍历右子树
        preorderTraversal(root.right, res);
    }
  • 非递归法1:教科书法
    public List<Integer> preorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<Integer>();
        }
        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        //初始化
        TreeNode curNode = root;
        while (curNode != null || ! stack.isEmpty()) { //两条件满足其一都要继续
            //将左边界一直入栈
            while (curNode != null) {
                stack.push(curNode);
                //第一次遇到该节点(先序遍历打印)
                res.add(curNode.val);
                curNode =curNode.left;
            }
            //第二次遇到该节点(中序遍历打印)
            curNode = stack.pop();
            //res.add(curNode.val);
            //转到该弹栈节点的右子树
            curNode = curNode.right;
        }
        return res;
    }
  • 非递归法2:
    public List<Integer> preorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<Integer>();
        }
        Stack<TreeNode> stack = new Stack<>();
        List<Integer> res = new ArrayList<>();
        //将根节点先入栈
        stack.push(root);
        while(! stack.isEmpty()) {
            //出栈便打印
            TreeNode popNode = stack.pop();
            res.add(popNode.val);
            //将出栈节点的右孩子,左孩子按顺序(如果它们不为空)入栈
            if (popNode.right != null) {
                stack.push(popNode.right);
            }
            if (popNode.left != null) {
                stack.push(popNode.left);
            }
        }
        return res;
    }
  • 非递归法3:金手指法
    public List<Integer> preorderTraversal(TreeNode root) {
        if (root == null) {
            return new ArrayList<Integer>();
        }
        List<Integer> res = new ArrayList<>();
        Stack<Command> stack = new Stack<>();
        //将初始状态设为遍历该树
        stack.push(new Command(false, root));
        while(! stack.isEmpty()) {
            Command curCommand = stack.pop();
            TreeNode curRoot = curCommand.root;
            if (curCommand.isPrint) {//如果状态是打印
                res.add(curRoot.val);
            }else {//如果状态是遍历,那么根据是何种遍历方式选择命令入栈的顺序
                //例如先序遍历是根(打印)左(遍历)右(遍历),那么入栈顺序则相反,
                //为右(遍历)左(遍历)根(打印)
                if (curRoot.right != null) {
                    stack.push(new Command(false, curRoot.right));
                }
                if (curRoot.left != null) {
                    stack.push(new Command(false, curRoot.left));
                }
                stack.push(new Command(true, curRoot));
            }
        }
        return res;
    }

//Command 类,用来表示当前是打印root节点值,还是遍历以root为根的树
class Command{
    boolean isPrint;
    TreeNode root;
    public Command(boolean isPrint, TreeNode root) {
        this.isPrint = isPrint;
        this.root = root;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值