如果说深度遍历是在一个方向上“一头扎到底”,那么广度遍历则恰恰相反,现在各个方向上走出第1步,再在各个方向上走出第2步,第3步…一直在各个方向上全部走完。学习二叉树层序遍历时,第一次发现数据结构还是挺有意思的,选用不同的数据结构,对完成数据操作的难易程度和效率都有很大影响,根据不同业务场景,选择合适的数据结构,至关重要。

二叉树广度优先遍历 java 二叉树的广度优先遍历_二叉树广度优先遍历 java

1.二叉树的广度优先遍历

详细遍历步骤如下

1)根节点1进入队列;

2)节点1出队, 输出节点1, 并得到节点1的左子节点2、 右子节点3, 让节点2和节点3入队;

3)节点2出队,输出节点2,并得到节点2的左子节点4、 右子节点

5, 让节点4和节点5入队;

4)节点3出队, 输出节点3, 并得到节点3的右子节点6,让节点6入

队;

5)节点4出队, 输出节点4, 由于节点4没有孩子节点, 所以没有新节点入队;

6)节点5出队, 输出节点5, 由于节点5没有孩子节点, 所以没有新节点入队;

7)节点6出队, 输出节点6, 节点6没有子节点, 没有新节点入队。

至此遍历完毕。

二叉树广度优先遍历 java 二叉树的广度优先遍历_子节点_02

3.配套代码

配套代码如下,TreeNode 类见上一篇博文

/**
     *二叉树广度遍历
     * @param root
     */
    public void levelOrderTraversal(TreeNode root){
        Queue<TreeNode> quene = new LinkedList<TreeNode>();
        quene.offer(root);
        while (!quene.isEmpty()){
            TreeNode node = quene.poll();
            System.out.println(node.data);
            if(node.left != null){
                quene.offer(node.left);
            }
            if(node.right != null){
                quene.offer(node.right);
            }
        }
    }

4.顺便说一下Queue

队列(Queue)是与栈相对的一种数据结构, 是集合(Collection)的一个子类。队列允许在一端进行插入操作,而在另一端进行删除操作的线性表,栈的特点是后进先出,而队列的特点是先进先出。队列的用处很大,比如实现消息队列。

4.1 Queue 继承结构

二叉树广度优先遍历 java 二叉树的广度优先遍历_子节点_03


从上图可以看出 Queue 大体可分为以下三类。

双端队列:双端队列(Deque)是 Queue 的子类也是 Queue 的补充类,头部和尾部都支持元素插入和获取。

阻塞队列:阻塞队列指的是在元素操作时(添加或删除),如果没有成功,会阻塞等待执行。例如,当添加元素时,如果队列元素已满,队列会阻塞等待直到有空位时再插入。

非阻塞队列:非阻塞队列和阻塞队列相反,会直接返回操作的结果,而非阻塞等待。双端队列也属于非阻塞队列。

4.2 Queue 方法

Queue 方法如图:

二叉树广度优先遍历 java 二叉树的广度优先遍历_子节点_04


其中比较常用的方法有以下几个:

add(E):添加元素到队列尾部,成功返回 true,队列超出时抛出异常;

offer(E):添加元素到队列尾部,成功返回 true,队列超出时返回 false;

remove(Object):删除元素,成功返回 true,失败返回 false;

peek():获取但不移除此队列的第一个元素,若队列为空,则返回 null;

poll():获取并移除此队列的第一个元素,若队列为空,则返回 null;

element():获取但不移除此队列的第一个元素,若队列为空,则抛异常。

更为详细我们会在后续展开。。。