2024王道408数据结构 P144 T14

2024王道408数据结构 P144 T14

思考过程

  1. 首先看题目,要求我们计算一棵二叉树的最大宽度,也就是结点最多的那一层的结点个数,很适合用层次遍历+辅助队列来实现。
  2. 每个结点还需要一个level值用来放结点的层数。

举个例子

层次遍历

  1. 首先we need a 队列q,队列需要有头尾指针,将他们初始化为-1q.f = q.r = -1;还需要一个指针p来存放出队的结点,还有一个变量k用来出队结点的层数。假设二叉树长这个样子请添加图片描述
  2. 首先我们先把头结点给入队,q.data[++q.r]=b;并且把level赋值为1,表示该结点在第一层q.level[q.r]=1;
  3. 将头结点入队之后我们开始进入循环,循环条件是q.f < q.r头指针一定要比尾指针小。进入循环的第一件事就是把此时的队尾元素出队,出队的同时用刚刚我们建立好的指针p来存放出队元素的值,p = q.data[++q.f]注意这里出队要移动队首指针f。出队之后就要判断该结点是否有左孩子和右孩子,如果有的话就入队,q.data[++q.r]=p->lchild;q.level[q.r]=k+1;注意这里很关键,入队的这个结点的层数要等于刚刚那个出队结点的层数+1,一定要理解这个地方,是该题的关键。 之后有右孩子也一样入队,也一样把右子树的level值赋为k+1,在例子中也就是把B和C入队,请添加图片描述
    到这里我们就完成了一次循环。我把每个元素的k值也标在队列上面。其实这里的出队并不完全算是出队,只能算是把队首指针f往后移动了。
  4. 循环往复知道二叉树中的全部结点都入队了,此时队列中应该是请添加图片描述循环一直出队,直到f指针和r指针相等退出循环。

计算每一层结点个数的最大值

  1. 那么现在我们所有结点都已经在队列当中了,我们需要变量n用来存放每个结点个数的值,max用来更新最大值,i用来遍历这个队列,此时k我们已经用完了,把它赋值为1表示我们从第一层开始遍历。
  2. 循环条件是i <= q.ri是从0开始遍历的,也就是从A结点开始往后移动,那么它肯定不能大于队尾指针。进入循环后先把n赋值为0,默认每一层有0个结点,然后进入第二层循环就是去计算n的值的,循环条件是q.level[i]==k当结点的level值和k值相等就表示该层有一个结点,就让n++,同时也让i++。比如例子中,现在k的值为1,结点A的level值也为1,那么表示第一层有一个结点,让n++。
  3. n++之后还要判断更新maxif(n>max) max = n;
  4. 遍历完第一层之后还要把k的值也更新为k = q.level[i]下一层。比如上面这个例子中第二层遍历完之后n就为2,此时把max的值也更新为2。然后再去遍历下一层。这题就做完了。

完整代码

//
// Created by 黎圣  on 2023/8/21.
//
/*
 * 假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树b的宽度
 * (即具有结点数最多的那一层的结点个数。)
 */
#include "iostream"
typedef struct TreeNode
{
    char data;
    struct TreeNode *lchild, *rchild;
}*tree;
struct Queue
{
    tree data[10];
    int f, r;
    int level[10];
};
void CreateTree(tree &t)
{
    char ch = getchar();
    if (ch == '#')
        t = NULL;
    else
    {
        t = (struct TreeNode *)malloc(sizeof(struct TreeNode));
        t->data = ch;
        t->lchild = NULL;
        t->rchild = NULL;
        CreateTree(t->lchild);
        CreateTree(t->rchild);
    }
}
int width(tree b)
{
    //辅助队列q
    Queue q;
    //指针p用来存放出队的元素
    struct TreeNode *p;
    //k用来记录出队结点的层次
    int k;
    //初始化队列
    q.r = q.f = -1;

    //入队根结点
    q.data[++q.r] = b;
    q.level[q.r] = 1;
    //层次遍历
    while (q.f < q.r)
    {
        //出队
        p = q.data[++q.f];
        k = q.level[q.f];

        if (p->lchild)
        {
            q.data[++q.r] = p->lchild;
            //进入队列的结点的层次为刚刚出队结点的层次+1
            q.level[q.r] = k + 1;
        }
        if (p->rchild)
        {
            q.data[++q.r] = p->rchild;
            q.level[q.r] = k + 1;
        }
    }
    //n用来记录每层的个数,max用来更新n的最大值,用i遍历队列
    int n, max = 0, i = 0;
    //此时元素已经全部入队了,k用来从第一层开始
    k = 1;
    while (i <= q.r)
    {
        //每层默认有0个结点
        n = 0;
        while (i <= q.r && q.level[i] == k)
        {
            //这一层的结点个数+1
            n++;
            i++;
        }
        //更新k的值让k去下一层
        k = q.level[i];
        if (n > max)
            max = n;
    }
    return max;
}
int main()
{
    tree t;
    CreateTree(t);
    //ABD##E##CF##G##
    printf("%d", width(t));
    return 0;
}
/*
             A
          B    C
        D  E  F  G
*/

这题我觉得也挺难的😭,最后感谢b站up主@吸血小金鱼

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
王道408数据结构的应用是指在408考试中出现的与数据结构相关的实际应用目。在这些目中,可能会涉及到顺序查找、折半查找、分块查找等算法王道书中给出了这些算法的代码实现,但对于考408的同学来说,掌握这些代码并不是必须的,因为408的代码没有像自主命那样深入和难度那么大。对于线性表的顺序表示、串以及栈和队列的实现,也不需要手写实现,可以使用标准库来解决问。只有在目要求你手动实现栈和队列等数据结构时,才需要进行手写实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [408王道数据结构强化——应用](https://blog.csdn.net/JiangNan_1002/article/details/125828454)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【23考研】计算机408数据结构代码强化阶段划重点(王道书)](https://blog.csdn.net/qq_50710984/article/details/125583743)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值