一、完全二叉树的定义
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。
(1)所有的叶结点都出现在第k层或k-l层(层次最大的两层)
(2)对任一结点,如果其右子树的最大层次为L,则其左子树的最大层次为L或L+l。
一棵二叉树至多只有最下面的两层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,则此二叉树成为完全二叉树,并且最下层上的结点都集中在该层最左边的若干位置上,而在最后一层上,右边的若干结点缺失的二叉树,则此二叉树成为完全二叉树
二、完全二叉树与非完全二叉树的结构对比图
三、判断一棵树是否是完全二叉树的代码分析
判断过程分为两阶段
先针对二叉树进行层序遍历
第一阶段:要求每个访问到的节点必须具备两个子树,如果遇到某个节点,没有子树,或者只有左子树,就进入第二阶段;如果只有右子树,那么就判定完毕,这个树就不是完全二叉树
第二阶段:要求每个访问到的节点必须没有子树,如果有子树就不是完全二叉树,直到遍历结束也没有找到不满足要求的节点,就是完全二叉树
代码如下
public boolean isComplete(TreeNode root) {
if (root == null) {
return true;
}
// 设定一个标志位,true 为第一阶段, false 为第二阶段
boolean isFiestStep = true;
// 层序遍历二叉树
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode cur = queue.poll();
if (isFiestStep) {
// 进入第一阶段,当前节点必须具备两个节点
if (cur.left == null && cur.right == null) {
// 左右子树都为空,进入第二阶段
isFiestStep = false;
}else if (cur.left != null && cur.right == null) {
// 左子树不为空,右子树为空,进入第二阶段,并将左子树入队列
isFiestStep = false;
queue.offer(cur.left);
}else if (cur.left == null && cur.right != null) {
// 左子树为空,右子树不为空,则不满足完全二叉树要求,返回 false
return false;
}else {
// 左右子树都不为空,将左右子树都入队列
queue.offer(cur.left);
queue.offer(cur.right);
}
}else {
// 第二阶段 当前节点左右子树为空
if (cur.left != null && cur.right != null) {
// 找到不满足要求的节点
return false;
}
}
}
// 遍历结束如果没找到不满足要求的节点,就是完全二叉树
return true;
}