二叉树的遍历

深度优先遍历(DFS)

  DFS是一种遍历策略,它从根节点开始,尽可能深地探索树的分支,直到达到叶节点,然后回溯至上一层节点的未访问子节点。

  对于二叉树,DFS有三种形式的遍历方式:

  • 前序遍历(Preorder Traversal):根节点 -> 左子树 -> 右子树
  • 中序遍历(Inorder Traversal):左子树 -> 根节点 -> 右子树
  • 后序遍历(Postorder Traversal):左子树 -> 右子树 -> 根节点
二叉树前、中、后序遍历
前序遍历

  遍历方式为先根节点,再左节点,最后右节点。

  • 递归实现
class treeNode{
    treeNode left;
    treeNode right;
    int val;
    public treeNode(int val){
        this.val = val;
    }
}
public void preOrder(treeNode root){
    if(root == null){
        return;
    }
    System.out.print(root.val + ",");
    preOrder(root.left);
    preOrder(root.right);
    // 递归实现
}
  • 非递归实现
// 使用栈这个数据结构
public ArrayList<Integer> preOrderTraversal(TreeNode root){
    Stack<TreeNode> stack = new Stack<TreeNode>();
    ArrayList<Integer> ans = new ArrayList<Integer>();
    if(root == null){
        return ans;
    }
    TreeNode cur = root;
    // 先将头节点push进来
    stack.push(cur);
    while(!stack.isEmpty()){
        cur = stack.pop();
        ans.add(cur.val);
        if(cur.right != null){
            stack.push(cur.right);
        }
        if(cur.left != null){
            stack.push(cur.left);
        }
    }
    return ans;
}
中序遍历

  遍历方式为先左节点,再根节点,最后右节点。

  • 递归实现
public void inOrder(treeNode root){
    if(root == null){
        return;
    }
    inOrder(root.left);
    System.out.print(root.val + ",");
    inOrder(root.right);
    // 递归实现
}
  • 非递归实现
public ArrayList<Integer> inOrderTraversal(TreeNode root){
    Stack<TreeNode> stack = new Stack<TreeNode>();
    ArrayList<Integer> ans = new ArrayList<>();
    TreeNode cur = root;
    while(cur != null || !stack.isEmpty()){
        if(cur != null){
            stack.push(cur);
            cur = cur.left;
        }else{
            cur = stack.pop();
            ans.add(cur.val);
            if(cur.rigth == null){
                cur = null;
            }else{
                cur = cur.right;
                stack.push(cur);
                cur = cur.left;
            }
        }
    }
    return ans;
}
后序遍历

  遍历方式为先左节点,再右节点,最后根节点。

  • 递归实现
public void postOrder(treeNode root){
    if(root == null){
        return;
    }
    postOrder(root.left);
    postOrder(root.right);
    System.out.print(root.val + ",")
}
  • 非递归实现
/**
主要思想:首先遍历root根节点的所有左节点,并依次入栈。对出栈的元素,如果没有右儿子或者虽然有右儿子但右儿子已完成遍历,即可完成出栈;否则,再次入栈,并把右儿子入栈,遍历右儿子的所有左儿子。
*/
public ArrayList<Integer> postOrder(treeNode root){
    Stack<TreeNode> stack = new Stack<TreeNode>();
    TreeNode cur = root;
    /*
    * 用来记录最新出栈的节点,如果当前节点的右儿子与flag相同,说明当前节点右子树已完成遍历
    */
    TreeNode flag = null;
    // 先找到最左边的儿子
    while(cur != null){
        stack.push(cur);
        cur = cur.left;
    }
    while(cur != null || !stack.isEmpty()){
        cur = stack.pop();
        // 判断该节点右子树是否为空或者已完成遍历
        if(cur.right == null || cur.right == flag){
            ans.add(cur.val);
            flag = cur;
        }else{
            // 反之右子树不为空,则需要重新入栈,直到右子树遍历完或右子树为空才可出栈
            stack.push(cur);
            cur = cur.right;
            // 找右子树的左儿子
            while(cur != null){
                stack.push(cur);
                cur = cur.left;
            }
        }
    }
    return ans;
}

广度优先遍历(BFS)

  BFS是一种从根节点开始,逐层遍历树的节点,每一层的所有节点都在下一层节点之前被访问。对于二叉树,BFS实现的是层次遍历,按照从上到下、从左到右的顺序访问节点:层次遍历(Level Order Traversal):首先访问第一层(根节点),然后是第二层的所有节点,接着第三层……直到最后一层。
  BFS使用队列数据结构来存储待访问节点,每次从队列头部取出节点并访问,然后将其子节点(如果存在且未访问过)添加到队列尾部。
例如,对于一棵二叉树,假设它的结构如下:

层次遍历

  一层一层的遍历:基于队列实现的自上而下,从左到右按层遍历二叉树,记录每一层节点的个数n,并出栈n次,这样就可以遍历完一层

public ArrayList<Integer> levelTraversal(TreeNode root){
    if(root == null){
        return null;
    }
    // 使用双向链表(LinkedList)来表示队列(Queue)
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    ArrayList<Integer> ans = new ArrayList<>();
    TreeNode cur = root;
    // 根节点进队
    queue.offer(cur);
    while(!queue.isEmpty()){
        // size记录当前层的节点数,用于完整遍历当前层节点
        for(int i = 0, size = queue.size(); i < size; i++){
            cur = queue.poll();
            ans.add(cur.val);
            // 先入栈left,自上而下,从左到右遍历
            if(cur.left != null){
                queue.offer(cur.left);
            }
            if(cur.right != null){
                queue.offer(cur.right);
            }
        }
    }
    return ans;
}
  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值