import java.util.LinkedList;

/**
* 判断二叉树是不是完全二叉树
* <p>
* 1)任何节点有右无左,不是完全二叉树
* 2)从第一个左右节点不双全的的节点开始,后续节点全是叶子结点
*/
public class IsCompleteBT {

public static boolean isCBT1(Node head) {
if (head == null) {
return true;
}
LinkedList<Node> queue = new LinkedList<>();
// 是否遇到过左右两个孩子不双全的节点
boolean leaf = false;
Node l = null;
Node r = null;
queue.add(head);
while (!queue.isEmpty()) {
head = queue.poll();
l = head.left;
r = head.right;
// 如果遇到了不双全的节点之后,又发现当前节点不是叶节点
if ((leaf && (l != null || r != null)) || (l == null && r != null)) {
return false;
}
if (l != null) {
queue.add(l);
}
if (r != null) {
queue.add(r);
}
if (l == null || r == null) {
leaf = true;
}
}
return true;
}

public static boolean isCBT2(Node head) {
if (head == null) {
return true;
}
return process(head).isCBT;
}

public static Info process(Node X) {
if (X == null) {
return new Info(true, true, 0);
}
Info leftInfo = process(X.left);
Info rightInfo = process(X.right);
int height = Math.max(leftInfo.height, rightInfo.height) + 1;
boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height;
boolean isCBT = false;
if (isFull) {
isCBT = true;
} else { // 以x为头整棵树,不满
if (leftInfo.isCBT && rightInfo.isCBT) {
if (leftInfo.isCBT && rightInfo.isFull && leftInfo.height == rightInfo.height + 1) {
isCBT = true;
}
if (leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height + 1) {
isCBT = true;
}
if (leftInfo.isFull && rightInfo.isCBT && leftInfo.height == rightInfo.height) {
isCBT = true;
}
}
}
return new Info(isFull, isCBT, height);
}

// 对每一棵子树,是否是满二叉树、是否是完全二叉树、高度
public static class Info {

public boolean isFull;

public boolean isCBT;

public int height;

public Info(boolean full, boolean cbt, int h) {
isFull = full;
isCBT = cbt;
height = h;
}

}

public static class Node {

public int value;

public Node left;

public Node right;

public Node(int data) {
this.value = data;
}

}

}

/* 如有意见或建议,欢迎评论区留言;如发现代码有误,欢迎批评指正 */