数据结构初阶之二叉树收尾

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;
}

判断算法(基于层序遍历)

核心思想:利用层序遍历,将所有节点的左右孩子(包括空节点)都入队。当遇到第一个空节点时,检查队列中剩余的所有节点,如果还有非空节点,则说明不是完全二叉树;否则是完全二叉树。

步骤:

  1. 将根节点入队。
  2. 循环直到队列为空:
  • 取出队首节点 top。

  • 如果 top == NULL,则遇到第一个空节点,跳出循环。

  • 否则,将 top->left 和 top->right 入队(无论是否为空)。

  1. 然后继续遍历队列剩余部分:
  • 如果遇到任何一个非空节点,则说明不是完全二叉树,返回 false。

  • 如果全部为空,返回 true。

关键点:

  • 为什么遇到第一个空节点就停止入队?

    因为在完全二叉树中,一旦出现空节点,该层之后的所有节点都应该是空。如果继续入队,可能会把后面的非空节点也入队,但我们只需要检查队列中已有的节点是否全是空。

  • 为什么第一阶段要把空节点也入队?

    这样才能保证我们能够遇到第一个空节点。如果只入队非空节点,那么遇到空节点时实际上队列中已经没有该空节点了,无法判断。

  • 第二阶段检查队列剩余节点:

    这些节点是在遇到第一个空节点之前就已经入队的,它们可能是后续的节点。如果其中有非空,说明在空节点之后还有节点,结构不符合完全二叉树。

我给大家再画图演示一下可能会更加清晰一些:

3.二叉树性质总结

一、满二叉树/完全二叉树性质

  1. 第 i 层最多节点数

    若规定根结点的层数为 (1),则一棵非空二叉树的第 (i) 层上最多有 (2^{i-1}) 个结点。

  2. 深度为 h 的二叉树的最大结点数

    若规定根结点的层数为 (1),则深度为 (h) 的二叉树的最大结点数是 (2^h - 1)(此时为满二叉树)。

  3. 满二叉树的深度

    若规定根结点的层数为 (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

相关推荐
oem1102 小时前
C++与Docker集成开发
开发语言·c++·算法
季远迩2 小时前
240. 搜索二维矩阵 II(中等)
人工智能·算法·矩阵
xushichao19892 小时前
C++中的享元模式
开发语言·c++·算法
tankeven2 小时前
HJ133 隐匿社交网络
c++·算法
m0_716667072 小时前
C++中的访问者模式高级应用
开发语言·c++·算法
Oueii2 小时前
C++中的访问者模式变体
开发语言·c++·算法
一叶落4382 小时前
【LeetCode 12】整数转罗马数字(C语言)| 贪心算法详解
c语言·数据结构·c++·算法·leetcode·贪心算法
2401_838683372 小时前
单元测试在C++项目中的实践
开发语言·c++·算法
一叶落4382 小时前
【LeetCode 289】生命游戏(C语言)|原地算法 + 状态标记法
c语言·数据结构·算法·leetcode·游戏