如果说深度遍历是在一个方向上“一头扎到底”,那么广度遍历则恰恰相反,现在各个方向上走出第1步,再在各个方向上走出第2步,第3步…一直在各个方向上全部走完。学习二叉树层序遍历时,第一次发现数据结构还是挺有意思的,选用不同的数据结构,对完成数据操作的难易程度和效率都有很大影响,根据不同业务场景,选择合适的数据结构,至关重要。
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没有子节点, 没有新节点入队。
至此遍历完毕。
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 继承结构
从上图可以看出 Queue 大体可分为以下三类。
双端队列:双端队列(Deque)是 Queue 的子类也是 Queue 的补充类,头部和尾部都支持元素插入和获取。
阻塞队列:阻塞队列指的是在元素操作时(添加或删除),如果没有成功,会阻塞等待执行。例如,当添加元素时,如果队列元素已满,队列会阻塞等待直到有空位时再插入。
非阻塞队列:非阻塞队列和阻塞队列相反,会直接返回操作的结果,而非阻塞等待。双端队列也属于非阻塞队列。
4.2 Queue 方法
Queue 方法如图:
其中比较常用的方法有以下几个:
add(E):添加元素到队列尾部,成功返回 true,队列超出时抛出异常;
offer(E):添加元素到队列尾部,成功返回 true,队列超出时返回 false;
remove(Object):删除元素,成功返回 true,失败返回 false;
peek():获取但不移除此队列的第一个元素,若队列为空,则返回 null;
poll():获取并移除此队列的第一个元素,若队列为空,则返回 null;
element():获取但不移除此队列的第一个元素,若队列为空,则抛异常。
更为详细我们会在后续展开。。。