完全二叉树的定义是:除了最后一层外,每一层都是完全填满的,并且最后一层的节点都尽可能地集中在左侧。
实现这个功能的步骤和代码:
第一步:初始化队列和变量
- 设定变量:我们需要一个队列来存储二叉树的节点,以及两个指针
front
和rear
来指示队列的头部和尾部。 - 初始化队列:将根节点入队,并将
front
和rear
设置为1,因为队列是空的,根节点是第一个元素。
bool fun(BTNode *p) {
BTNode *q[maxsize]; // 定义队列
int front = 0, rear = 0; // 初始化队列的头和尾指针
if (p == NULL) // 如果树为空,直接返回true
return true;
q[++rear] = p; // 根节点入队,rear自增表示队列尾部移动
}
第二步:遍历二叉树
- 遍历队列:当队列不为空时,从队列头部取出一个节点。
- 处理节点:对于取出的节点,将其左孩子和右孩子分别入队。如果节点为空,继续处理下一个节点。
while (front != rear) { // 当队列不为空时
p = q[++front]; // 取出队列头部的节点,front自增
if (p != NULL) { // 如果节点不为空
q[++rear] = p->lchild; // 左孩子入队
q[++rear] = p->rchild; // 右孩子入队
}
}
第三步:检查队列中的节点是否为空
检查队列中的节点是否为空,而不是检查它们是否有孩子。如果一个节点为空,那么它不应该被入队
while (front != rear) {
p = q[++front];
if (p != NULL) {
if (p->lchild != NULL) q[++rear] = p->lchild;
if (p->rchild != NULL) q[++rear] = p->rchild;
}
}
第四步:检查是否为完全二叉树
- 检查剩余节点:如果队列中还有节点,说明不是完全二叉树,返回false。
- 返回结果:如果队列为空,说明是完全二叉树,返回true。
while (front != rear) { // 检查队列是否还有剩余节点
p = q[++front]; // 取出队列头部的节点
if (p != NULL) // 如果节点不为空
return false; // 不是完全二叉树
}
return true; // 是完全二叉树
完整的代码
bool fun(BTNode *p) {
BTNode *q[maxsize]; // 定义队列
int front = 0, rear = 0; // 初始化队列的头和尾指针
if (p == NULL) // 如果树为空,直接返回true
return true;
q[rear++] = p; // 根节点入队,rear自增表示队列尾部移动
while (front != rear) { // 当队列不为空时
BTNode *node = q[front++]; // 取出队列头部的节点,front自增
if (node != NULL) { // 如果节点不为空
if (node->lchild != NULL) q[rear++] = node->lchild; // 左孩子入队
if (node->rchild != NULL) q[rear++] = node->rchild; // 右孩子入队
}
}
while (front != rear) { // 检查队列是否还有剩余节点
BTNode *node = q[front++]; // 取出队列头部的节点
if (node != NULL) // 如果节点不为空
return false; // 不是完全二叉树
}
return true; // 是完全二叉树
}
1
/ \
2 3
/ \ \
4 5 6
解释代码中的变量变化:
-
初始化队列
q
和队列的头尾指针front
和rear
。初始时,front = 0
和rear = 0
。 -
检查根节点
p
是否为空,如果不为空,则将根节点入队,rear
自增到 1。 -
开始循环,直到队列为空(
front != rear
):-
第一次循环,取出队列头部的节点(根节点 1),
front
自增到 1。因为节点不为空,所以将左孩子(节点 2)和右孩子(节点 3)入队,rear
自增到 3。 -
第二次循环,取出队列头部的节点(节点 2),
front
自增到 2。因为节点不为空,所以将左孩子(节点 4)和右孩子(节点 5)入队,rear
自增到 5。 -
第三次循环,取出队列头部的节点(节点 3),
front
自增到 3。因为节点不为空,所以将左孩子(节点 6)入队,rear
自增到 6。注意,节点 3 没有右孩子,所以不会入队。
-
-
此时,队列中还有节点(节点 4、5、6),所以继续循环:
-
第四次循环,取出队列头部的节点(节点 4),
front
自增到 4。因为节点为空(在完全二叉树中,如果一个节点没有左孩子,那么它也没有右孩子),所以不进行任何操作。 -
第五次循环,取出队列头部的节点(节点 5),
front
自增到 5。同上,不进行任何操作。 -
第六次循环,取出队列头部的节点(节点 6),
front
自增到 6。同上,不进行任何操作。
-
-
此时,队列为空(
front == rear
),所以退出循环,并返回true
,表示这是一棵完全二叉树。