二叉树专题(一)——二叉树结构和层序遍历

一、二叉树结构基础知识

1、二叉树的定义

 二叉树是满足以下任一一个条件的有限的节点集合:1、为空集 2、由一个根节点和两个不相交的 二叉树 构成,分别成为左子树和右子树。

 二叉树对应的算法也本质上是递归 的,包括两部分:1、简单的基本情况——最简单的二叉树是空集2、由其他情况还原为简单情况——不是空集的二叉树都可以分为一个节点和两个不相交的二叉树

 2、二叉树的存储结构

 二叉树通过自定义类TreeNode来存储,一个节点类包含三个部分: 值 val 和 左子树 leftNode 和 右子树 rightNode

认为树的值为整型,则可以通过如下结构存储二叉树

class TreeNode{

      int val;

      TreeNode leftNode;

      TreeNode rightNode;

}

二、二叉树层序遍历

1、深度优先遍历 DFS 和广度优先遍历 BFS

深度优先遍历DFS和广度优先遍历BFS均为树/树/图的搜索方式,能够访问树/树/图中的所有节点。

深度优先遍历DFS——优先移动节点,当对给定节点尝试过每一种可能性之后,才退到前一 节点来尝试下一个位置。 就像一个搜索者尽可能地深入调查未知的地域,直 到遇到死胡同才回头。

广度优先遍历BFS——优先对给定节点的下一个位置进行进行尝试,当对给定节点尝试过每一种可能性之后,才移动到下一个节点。就像一只搜索军队铺展开来覆盖领土,直到覆盖了所有地域,类似水的涟漪,一层一层一圈一圈的搜索。

DFS借助数据结构Stack栈实现,BFS借助数据结构Queue队列实现。

2、树的层序遍历

树的层序遍历就是树的的广度优先遍历——从上到下、从左到右访问树中的节点,每一层的节点都按顺序出现。

进行树的广度优先遍历,需要借助数据结构Queue队列来实现。

3、树的层序遍历模板

// 二叉树的层序遍历( LeetCode 102 ):https://leetcode-cn.com/problems/binary-tree-level-order-traversal
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        // 设置 res 用来保存输出结果
        List<List<Integer>> res = new LinkedList<>();
        // 边界情况处理
        if(root == null) return res;
        
        // 设置一个队列,用来存储二叉树中的元素
        Queue<TreeNode> queue = new LinkedList<>();
        // 队列添加二叉树的根节点
        queue.add(root);

        // 遍历队列,直到队列为空,说明访问了二叉树中所有的节点
        while(!queue.isEmpty()){  
            // 用来记录 queue 的长度,即每层节点的个数
            int size = queue.size();  

            // 用来保存每一层节点,保存成功后添加到 res 中
            List<Integer> temp =  new ArrayList<>(); 
  
            // 使用 for 循环,将 queue 中的元素添加的 temp 中
            for(int i = 0 ; i < size ;  i++ ){     
                // 从 queue 中取出一个节点         
                TreeNode node = queue.poll();  
                // 把节点存放到 list 中
                temp.add(node.val);  //将节点值加入list

                // 判断当前节点的左子节点是否有值,如果有,则添加到 queue 中
                if(node.left != null)
                    queue.add(node.left);

                // 判断当前节点的右子节点是否有值,如果有,则添加到 queue 中    
                if(node.right != null)
                    queue.add(node.right);
            }

            // 把存放了每一层元素的数组 temp 添加到 res 中
            res.add(temp);
        }

        // 返回 res
        return res; 
    }
}
4、模板的思路步骤

(1)边界情况处理,一般是判断根节点为空时,答案的处理以及返回情况:例如若根节点为空,返回一个空列表。

List<List<Integer>> res = new LinkedList<>();
        // 边界情况处理
if(root == null) 
   return res;

(2)维护一个队列,用于 BFS 过程,初始化队列,加入根节点

Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);

(3)使用while循环进行BFS,退出循环的条件是队列为空获得当前队列的长度qSize,为二叉树该层节点数。初始化子列表temp,用于储存二叉树该层节点的值。循环 qSize 次,遍历该层的节点,令队头的节点 node 出队,将 node 的值加入子列表temp中。

while(!queue.isEmpty()){  
            // 用来记录 queue 的长度,即每层节点的个数
            int qSize = queue.size();  

            // 用来保存每一层节点,保存成功后添加到 res 中
            List<Integer> temp =  new ArrayList<>(); 
  
            // 使用 for 循环,将 queue 中的元素添加的 temp 中
            for(int i = 0 ; i < qSize ;  i++ ){     
                // 从 queue 中取出一个节点         
                TreeNode node = queue.poll();  
                // 把节点存放到 list 中
                temp.add(node.val);  //将节点值加入list
                ......
            }
            ......
}

(4)判断队头结点node的左右子节点是否存在,若node的左节点存在,入队,若node的右节点存在,入队

  // 遍历队列,直到队列为空,说明访问了二叉树中所有的节点
        while(!queue.isEmpty()){  
            // 用来记录 queue 的长度,即每层节点的个数
            int size = queue.size();  

            // 用来保存每一层节点,保存成功后添加到 res 中
            List<Integer> temp =  new ArrayList<>(); 
  
            // 使用 for 循环,将 queue 中的元素添加的 temp 中
            for(int i = 0 ; i < size ;  i++ ){     
                // 从 queue 中取出一个节点         
                TreeNode node = queue.poll();  
                // 把节点存放到 list 中
                temp.add(node.val);  //将节点值加入list

                // 判断当前节点的左子节点是否有值,如果有,则添加到 queue 中
                if(node.left != null)
                    queue.add(node.left);

                // 判断当前节点的右子节点是否有值,如果有,则添加到 queue 中    
                if(node.right != null)
                    queue.add(node.right);
            }
            ......
}

(5)经过循环qSize次后,将子列表加入答案列表,最后退出while循环,返回答案列表

public List<List<Integer>> levelOrder(TreeNode root) {
       ......
        // 遍历队列,直到队列为空,说明访问了二叉树中所有的节点
        while(!queue.isEmpty()){  
            // 用来记录 queue 的长度,即每层节点的个数
            int size = queue.size();  

            // 用来保存每一层节点,保存成功后添加到 res 中
            List<Integer> temp =  new ArrayList<>(); 
  
            // 使用 for 循环,将 queue 中的元素添加的 temp 中
            for(int i = 0 ; i < size ;  i++ ){     
                // 从 queue 中取出一个节点         
                TreeNode node = queue.poll();  
                // 把节点存放到 list 中
                temp.add(node.val);  //将节点值加入list

                // 判断当前节点的左子节点是否有值,如果有,则添加到 queue 中
                if(node.left != null)
                    queue.add(node.left);

                // 判断当前节点的右子节点是否有值,如果有,则添加到 queue 中    
                if(node.right != null)
                    queue.add(node.right);
            }

            // 把存放了每一层元素的数组 temp 添加到 res 中
            res.add(temp);
        }

        // 返回 res
        return res; 
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值