1.层序遍历
c
void LevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
QueuePush(&q, root); // 根节点入队
while (!QueueEmpty(&q))
{
BTNode* top = QueueFront(&q); // 取出队首
printf("%c ", top->data); // 访问
QueuePop(&q); // 弹出
if (top->left) // 左孩子非空则入队
QueuePush(&q, top->left);
if (top->right) // 右孩子非空则入队
QueuePush(&q, top->right);
}
QueueDestroy(&q);
}
层序遍历是什么意思,它又被称为广度优先遍历。
算法思想:
层序遍历就是从上到下、从左到右依次访问每个节点。
-
它借助队列实现:
-
先将根节点入队。
-
只要队列不为空,就重复:
-
取出队首节点,访问它。
-
如果该节点有左孩子,将左孩子入队。
-
如果该节点有右孩子,将右孩子入队。
-
这样就能保证先访问第1层,再第2层,同一层从左到右。
我们这里可以画个图给大家来解释一下:

这里给大家画了第一步,后面就不再演示了,这里不就是按照上面的逻辑嘛。
把根节点弹出,插入根节点的左右节点,然后再弹出2,插入3,依次循环即可,知道队列为空。
2.判断完全二叉树
c
bool BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
QueuePush(&q, root);
// 第一阶段:按层序遍历,直到遇到第一个空节点
while (!QueueEmpty(&q))
{
BTNode* top = QueueFront(&q);
QueuePop(&q);
if (top == NULL)
{
break; // 遇到第一个空节点,停止入队
}
// 不管孩子是否为空,都入队
QueuePush(&q, top->left);
QueuePush(&q, top->right);
}
// 第二阶段:检查队列中剩余的所有节点
while (!QueueEmpty(&q))
{
BTNode* top = QueueFront(&q);
QueuePop(&q);
if (top != NULL)
{
QueueDestroy(&q);
return false; // 发现非空节点,不是完全二叉树
}
}
QueueDestroy(&q);
return true;
}
判断算法(基于层序遍历)
核心思想:利用层序遍历,将所有节点的左右孩子(包括空节点)都入队。当遇到第一个空节点时,检查队列中剩余的所有节点,如果还有非空节点,则说明不是完全二叉树;否则是完全二叉树。
步骤:
- 将根节点入队。
- 循环直到队列为空:
-
取出队首节点 top。
-
如果 top == NULL,则遇到第一个空节点,跳出循环。
-
否则,将 top->left 和 top->right 入队(无论是否为空)。
- 然后继续遍历队列剩余部分:
-
如果遇到任何一个非空节点,则说明不是完全二叉树,返回 false。
-
如果全部为空,返回 true。
关键点:
-
为什么遇到第一个空节点就停止入队?
因为在完全二叉树中,一旦出现空节点,该层之后的所有节点都应该是空。如果继续入队,可能会把后面的非空节点也入队,但我们只需要检查队列中已有的节点是否全是空。
-
为什么第一阶段要把空节点也入队?
这样才能保证我们能够遇到第一个空节点。如果只入队非空节点,那么遇到空节点时实际上队列中已经没有该空节点了,无法判断。
-
第二阶段检查队列剩余节点:
这些节点是在遇到第一个空节点之前就已经入队的,它们可能是后续的节点。如果其中有非空,说明在空节点之后还有节点,结构不符合完全二叉树。
我给大家再画图演示一下可能会更加清晰一些:

3.二叉树性质总结
一、满二叉树/完全二叉树性质
-
第 i 层最多节点数
若规定根结点的层数为 (1),则一棵非空二叉树的第 (i) 层上最多有 (2^{i-1}) 个结点。
-
深度为 h 的二叉树的最大结点数
若规定根结点的层数为 (1),则深度为 (h) 的二叉树的最大结点数是 (2^h - 1)(此时为满二叉树)。
-
满二叉树的深度
若规定根结点的层数为 (1),具有 (n) 个结点的满二叉树的深度 (h = log_2(n+1))((log) 以 (2) 为底)。
二、一般二叉树性质
**对任何一棵二叉树,如果度为 (0) 的叶结点个数为 (n_0),度为 (2) 的分支结点个数为 (n_2),则有:
n_0 = n_2 + 1\]** ### 4.二叉树的性质小练习 #### 4.1题目1 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( ) * A .不存在这样的二叉树 * B .200 * C .198 * D .199 解析: 根据二叉树的性质:对于任何一棵二叉树,叶子结点数 (n_0) 与度为 2 的结点数 (n_2) 满足关系: \[n_0 = n_2 + 1
已知 (n_2 = 199),则 (n_0 = 199 + 1 = 200)。
选项 B 正确。
4.2 题目2
在具有 (2n) 个结点的完全二叉树中,叶子结点个数为( )
- A .(n)
- B .(n+1)
- C .(n-1)
- D .(n/2)
解析:

我们可以想到,完全二叉树的情况,是不是要不N1就为1,要不N1就根本没有啊,那么在这道题里,我们想要保证等式右边为偶数,左边是不是一定为奇数呀,所以在这里N1等于1,所以N0等于n
因此答案为 A。
4.3题目3
一棵完全二叉树的结点数为 531 个,那么这棵树的高度为( )
- A .11
- B .10
- C .8
- D .12
解析:
完全二叉树的高度 (h) 满足:深度为 (h) 的满二叉树节点数为 (2^h - 1),深度为 (h-1) 的满二叉树节点数为 (2^{h-1} - 1)。
对于此题,我们可以使用排除法,我们想,如果是完全二叉树,假设高度为h,那么前h-1层是不是都是满的,最后一层可能为1,也可能是满的对不对,所以在本题中,因为总节点数为531,所以只需看是否满足合适区间就可以了:
对于A选项,2的11次方等于2048,就算再减去最后一层,也就是最小值,也得有1000个往上,所以A肯定错
同理,D选项绝对错
我们来看B选项,2的10次方等于1024,也就是说最多有1023个节点,那么最少是不是有511呀,511<531<1023,区间合理,保险起见,我们来看C选项
对于C选项,2的8次方等于512-1等于511,最大都没有达到531,所以不可能。
综上所述,因此答案为 B。
4.4题目4
一个具有 767 个结点的完全二叉树,其叶子结点个数为( )
- A .383
- B .384
- C .385
- D .386
解析:
还是同上一样分析:
因为节点为奇数,所以在这里N1等于0

因此答案为 B。
5.链式二叉树遍历小练习
5.1题目1
某完全二叉树按层次输出(同一层从左到右)的序列为 ABCDEFGH。该完全二叉树的前序序列为( )
- A .ABDHEFCG
- B .ABCDEFGH
- C .HDBEAFCG
- D .HDEBFGCA
这题还是很简单的,先把图画出来就好了:

因此,答案为A。
5.2题目2
二叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG。则二叉树根结点为( )
- A . E
- B. F
- C. G
- D .H
此题同理,画图即可:

答案:A
5.3题目3
设一棵二叉树的中序遍历序列:badce,后序遍历序列:bdeca,则二叉树前序遍历序列为____。
- A .adbce
- B .decab
- C .debac
- D .abcde
同理,画图:

所以前序遍历为:abcde
答案:D
5.4题目4
某二叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF,则按层次输出(同一层从左到右)的序列为
- A. FEDCBA
- B .CABFED
- C .DEFCBA
- D .ABCDEF
同上,画图:

因此,答案:A