LeetCode做题笔记-二叉树的遍历

本文介绍了二叉树的四种遍历方法——前序、中序、后序和层序遍历,分别给出了递归和迭代两种实现方式。在迭代实现中,利用栈来模拟递归过程,对于层序遍历则使用了队列。
摘要由CSDN通过智能技术生成

二叉树的遍历

给你二叉树的根节点 root ,返回其节点值的前序、中序、后序、层序遍历。
在这里插入图片描述

使用迭代的方式实现递归函数,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来

前序遍历-递归与迭代

public void preOrder(TreeNode root, List<Integer> res) {
    //根左右
    if (root == null) {
        return;
    }
    res.add(root.val);
    preOrder(root.left, res);
    preOrder(root.right, res);
}
---------------------------------------------------------------------
public List<Integer> preorderTraversal(TreeNode root) {
    // 使用栈模拟递归
    List<Integer> list = new ArrayList<Integer>();
    if (root != null) {
        Stack<TreeNode> stack = new Stack<>();
        stack.add(root);// 根节点压入栈中
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            if (node != null) {
                list.add(node.val);
                // 这里需要先把右子树先压入栈中(因为需要先弹出左子树)
                stack.push(node.right);
                stack.push(node.left);
            }
        }
    }
    return list;
}

中序遍历-递归与迭代

public void inOrder(TreeNode root, List<Integer> res) {
    //左根右
    if (root == null) {
        return;
    }
    inOrder(root.left, res);
    res.add(root.val);
    inOrder(root.right, res);
}
---------------------------------------------------------------------
public List<Integer> inorderTraversal(TreeNode root) {
    // 使用栈模拟递归
    List<Integer> list = new ArrayList<Integer>();
    if (root != null) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while (!stack.isEmpty() || root != null) {// 同时需要找到最左边的节点
            if (root != null) {// 一直找最左边的节点并把节点压入栈中
                stack.push(root);
                root = root.left;
            } else {// 找到最左边的节点
                root = stack.pop();// 弹出最左的节点
                list.add(root.val);
                root = root.right;// 最左的节点可能有右子节点,也可能没有
            }
        }
    }
    return list;
}

后序遍历-递归与迭代

public void postOrder(TreeNode root, List<Integer> res) {
    //左右根
    if (root == null) {
        return;
    }
    postOrder(root.left, res);
    postOrder(root.right, res);
    res.add(root.val);
}
---------------------------------------------------------------------
public List<Integer> postorderTraversal(TreeNode root) {
    // 左右根
    List<Integer> list = new ArrayList<Integer>();
    TreeNode prev = null;// 记录是否被打印
    if (root != null) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while (!stack.isEmpty() || root != null) {// 同时需要找到最左边的节点
            while (root != null) {// 一直找最左边的节点并把节点压入栈中
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();// 弹栈
            if (root.right == null || root.right == prev) {// 右子节点为空或已经加入list
                list.add(root.val);
                prev = root;// 记录右子节点已经加入list
                root = null;// 赋值为null,防止进入下次循环
            } else {
                // 有右子节点或右子节点未加入list,则将该节点入栈并指向该右子节点
                stack.push(root);
                root = root.right;
            }
        }
    }
    return list;
}

层序遍历-递归与迭代

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        // 可以发现,满二叉树节点的下标都是固定的(根节点的序号为i,则左子树序号为2*i,右子树为2*i+1)
        if (root == null) {
            return new ArrayList<List<Integer>>();
        }
        ArrayList<List<Integer>> list = new ArrayList<List<Integer>>();
        return dfs(root, 1, list);
    }

    private List<List<Integer>> dfs(TreeNode root, int i, ArrayList<List<Integer>> list) {
        if (list.size() < i) {
            // 当list大小不能放下新list时,需要使用add扩容
            list.add(new ArrayList<Integer>());
        }
        list.get(i - 1).add(root.val);// 放入当前节点的值
        if (root.left != null) {
            dfs(root.left, i + 1, list);
        }
        if (root.right != null) {
            dfs(root.right, i + 1, list);
        }
        return list;
    }
}
---------------------------------------------------------------------
public List<List<Integer>> levelOrder(TreeNode root) {
    if (root == null) {
        return new ArrayList<List<Integer>>();
    }
    // 使用迭代实现层序遍历需要使用队列
    ArrayList<List<Integer>> list = new ArrayList<List<Integer>>();
    Queue<TreeNode> q = new LinkedList<>();
    q.add(root);
    while (!q.isEmpty()) {
        int size = q.size();// 获取当前层的节点数(当前队列长度=前层的节点数)
        ArrayList<Integer> temp = new ArrayList<Integer>();
        for (int i = 0; i < size; i++) {// 这里也是一样的必须使用size变量
            TreeNode node = q.remove();// 取出队列节点
            temp.add(node.val);
            if (node.left != null) {
                q.add(node.left);
            }
            if (node.right != null) {
                q.add(node.right);
            }
        }
        // 将此层的节点放入list
        list.add(temp);
    }
    return list;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值