题目
给定一个二叉树,判定是否完全二叉树?
完全二叉树定义如下:
若二叉树的深度是h
,除了第h层
之外,其他各个层的节点数量都达到了最大的个数;第h层
的叶子节点都连续集中在最左边,这就是完全二叉树。
满二叉树一定是完全二叉树,反之则不然。
示例:

涉及知识点
队列
队列是一种仅仅支持在表尾插入操作、表头进行删除操作的线性表,插入端称之为队尾,删除端称之为队头。满足先进先出原则,元素入队即将新元素加在队列的尾,元素出队即将队首元素取出,它后一个作为新的队首。
Java的Queue API介绍
Java队列主要分为了阻塞
、非阻塞
、单向链表
、以及双向链表
。
- 阻塞队列:若入队元素超过了限定值,则会等待阻塞,等待队列元素出队之后,元素数量没有超过限定数值才开始继续入队列。
- 非阻塞队列:不管出队还是入队,不会阻塞;入队若超出了限定值,则抛出异常;出队时,若队列空,则取出空值。
Java队列的接口继承关系图:

Java队列常用方法
- remove:移除返回队列头部元素;若队列空,则给出NoSuchElementException异常。
- element:返回队列头部元素;若队列空,则给出NoSuchElementException异常。
- offer:添加一个元素并且返回true;若队列满了,则返回false。
- poll:删除并且返回队列头部的元素;若队列空,则返回null。
- peek:返回队列头部的元素;若队列空,则返回null。
- put:添加一个元素;若队列满,则阻塞等待。
非阻塞队列
- ConcurrentLinkedQueue
单向链表结构的无界并发队列, 非阻塞队列,由CAS实现线程安全,内部基于节点实现。
关于CAS:CAS算法。
- ConcurrentLinkedDeque
双向链表结构的无界并发队列, 非阻塞队列,由CAS实现线程安全。
- PriorityQueue

优先队列,是0或者多个元素构成的集合,并且在集合中,按照某种排序方式(元素自身的权重)来进行排序,不会保证元素内部整体有序,但是每次弹出的元素优先级最高或者最低。
其内部数据结构是堆。堆底层是完全二叉树,对于树的存储包含有链式存储或者顺序存储
。PriorityQueue使用了顺序存储,所以利用了Object[]数组,然后利用完全二叉树的性质,解决了父子节点关系的问题。
注意:默认实现是小根堆。
解题思路
对于完全二叉树最重要的定义就是叶子节点只能够出现在最下层或者次下层。因此我们可以利用辅助队列来来实现层序遍历——从上层遍历到下层,每一层从左至右。
步骤
- 首先判定空树一定是完全二叉树。
- 初始化一个队列,加入根节点。
- 从队列弹出元素访问节点,若某个节点空,标记。表示遍历到了完全二叉树的最下层,若后续依然还有访问,则提前出现了叶子节点,返回false。
- 继续加入左右子树的节点进入队列,等待访问。
代码