uva122树的层次遍历全过程详解-紫书题分析

本文详细介绍了UVA122题目的解决方案,重点讲解了如何通过自定义结构体建立树并进行层次遍历。讨论了在处理大量节点但树结构稀疏的情况下,避免编号和动态分配空间的方法。文章提供了输入处理、数据解析、节点添加及层次遍历的步骤,包括相关函数的伪代码和解释。
摘要由CSDN通过智能技术生成

原题链接-洛谷
代码是模仿lrj大神的,在这里主要写一些自己的理解和分析,希望可以帮助大家理解这道题。

本题的最大节点数为256,且并未指出最大深度,所以如果用编号思想的话,要编号到2的256次方,我们都知道这是个天文数字,即使用高精度也是不好做的。而且我们完全没有必要用到编号,因为即使编号了,这课树的绝大多数编号也都是没有被使用的,(最坏情况下是大概是2的256次方-256个未使用),所以可以说这棵树是很稀疏的一棵树。
那么我们就只能用另外一种方法了,就是用几个节点就申请多大的空间。更好的事情是,我们可以在最后释放这些空间。

以下是代码实现过程

一、分析题目的输入组数
我们发现可能出现多组数据输入输出的情况,遇到这种情况时,我们的主函数模板一般是这样的:
情况一(没有事先给出输入组数的时候):
while(输入函数返回值为TRUE){
将答案保存起来,然后输出,或者直接输出。
}
这里的输入函数可能是scanf语句或者cin,比如有些题会说明以-1为结束,可以这样写
while(scanf("%d",&k)==1 && k!=-1);
也可能是m,n两个,同样道理。
这个输入函数也可以是根据具体题目情况自定义的函数,比如这道题我采用的就是自定义函数。
情况二(给出输入组数):
这个比较简单,可以先输入组数t,然后while(t --){}即可。
二、分析基本解题思路
1、因为不能编号,所以我们采用自定义的结构体链接整棵树。
2、输入方式我们用自定义的输入函数来解决。
3、先建树,再bfs。
4、很多同学可能思考到这一步就比较凌乱,不知道之后该怎么做,这时我推荐我们可以一开始不要思考太多,可以先开始做题,然后慢慢发现问题,慢慢把代码写出来。
三、直接先能写多少写多少,先写出主函数的框架。
下面是伪代码:

int main(){
   
    
    //申请一个数组用来存答案;
    while(自己写的读入数据的函数(),读入同时就可以建树){
   
          bfs;
          输出数据;
    }
    return 0;
}

四、进一步思考,如何来读取数据
这时看输入样例,我们发现所有的插入的结点之间都是空格隔开的,这时推荐用scanf来写,并且每一组都有唯一的结束标志(),所有输入彻底结束的标志是“没有标志”,也就是没有任何数据继续读入时,读入数据要立即结束。也可以理解为scanf返回值非1(就是读不到东西了)所以框架继续搭建。

char s[1001005];
bool read_tree(void){
   
    while(true){
   
        if(scanf("%s",s)!=1) return false;//如果读不到东西,返回false,这样主函数的循环就结束了
        if(!strcmp(s,"()")) break;//如果遇到括号,只代表这一组数据结束。
        解析输入格式并处理数据...
    }
    return true;
}

这样就能把数据读进来了,虽然只是存在字符数组中,还没有进行解析,但是我们这个时候可以把我们读到的东西试着原样输出一下,调试一下有没有问题,对于这种比较复杂的程序,逐个调试子函数是很有必要的,这样可以尽量避免写完所有之后,找半天不知道到底哪个地方有错。
五、对于读入的数据进行解析
我们之前只把数据读在了字符数组里面,但是这道题的目标是把依靠数据建树,所以我们要进行解析。首先我们可以很直观地看到我们读的数据分为两个部分,以输入样例为例子,我们读进来的第一个s的内容是(11,LL),它的两个部分是11 和 LL 括号和逗号都是我们不要的。

所以我们现在来解析s数组。
1、解析出新节点的权值: 这时我们要先学习一个新的知识,sscanf函数,我的理解是,它的作用是将其第一个参数当做用户输入的内容来进行输入,后两个参数和我们熟悉的scanf函数的两个参数无异。
以(11,LL)为例,11是我们要加的点的权值,我们定义一个变量叫做val来存它(value的简写),然后请读者仔细理解这个语句:

sscanf(&s[1],"%d",&val);

其实就相当于我们用scanf语句读入数据时,用户写在那个黑框里面敲的是11,LL) 一样。这个语句读了11,舍弃了其它的,因为其它不是整型数据。有同学会问,为什么少了个括号。注意看这一句里面是s[1],代表是从s的第一个而不是第0个字符开始的。另外要记得加取地址符号。

2、接下来要解决的是解析出位置,就是LL部分,我们又要学习一个新知识,strchr函数,它有两个参数,第一个是字符串,第二个是字符,所以它的名字很好记,string和char的结合,strchr,作用是返回指定字符串中第一个该字符的地址。注意这个表达式:

strchr(s,’,’)+1

这个运算结果会返回s字符串中逗号地址再加一,也就是(11,LL)例子中的第一个L的地址。
有了这个地址,我们就能找到s字符串中逗号之后的内容了,至此我们就完成了对读入数据的解析。接下来我们进一步完善我们的读入数据函数。

六、完善读入数据函数:

bool read_tree(void){
   
    failed=false;
    while(true){
   
        if(scanf("%s",s)!=1) return false;
        if(!strcmp(s,"()")) break;
        int val;
        sscanf(&s[1],"%d",&val);
        add_node(val,strchr(s,',')+1);
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值