uva122树的层次遍历 题解

题干

UVA122 树的层次遍历 Trees on the level

题目描述

树状结构在电脑科学的许多领域中都相当重要。本问题牵涉到建立树及遍历树。

给您一个二叉树,您的任务是写一个程序来输出依「阶层(level-order)」遍历的结果。在本问题中,二叉树的每个节点含有一个正整数,并且节点的数目在 [1,256] 的范围内。

在「阶层」遍历中,依阶层从低到高,同阶层从左到右的次序来列印。
例如下面这个二叉树的阶层遍历结果就为
5,4,8,11,13,4,7,2,1

在本问题中,二叉树以节点来表示。每个节点以一个有序数对 $(n,s)$ 来表示:

  • n 代表此节点的值
  • s 代表一个字符串,代表从根节点到达此节点的路径,其中 L 代表左,R 代表右

比如说上面那个值为 13 的节点用 (n,s) 的表示法就为 (13,RL),值为 2的节点用 (n,s) 的表示法就为 (2,LLR),根节点 5用 (n,s) 的表示法就为 (5,)。
输入格式
首先说明,我们定义 代表空格或换行符。
输入包含多组测试数据。
每组测试数据为若干节点的集合。各节点间以 空格或换行 分隔。
注意:在各节点内(也就是左右括号之间)不会有 空格或换行 ,当遇到 () 的节点,代表该组测试数据结束。
输出格式
对于每组测试数据,如果输入的节点可以正常的构成一个二叉树的话,请输出按「阶层」遍历的结果。如果输入的节点无法正常的构成一个二叉树的话,也就是说有某些该有的节点没有给,或者重复给(同一个路径上有 $2$ 个节点),请输出 not complete
输入输出样例
输入

(11,LL) (7,LLL) (8,R)
(5,) (4,L) (13,RL) (2,LLR) (1,RRR) (4,RR) ()
(3,L) (4,R) ()

输出

5 4 8 11 13 4 7 2 1
not complete

节点数最少 1个,最多 256个。

思路

大体思路很简单,只需要读入节点,根据节点的信息创建树,并进行BFS遍历即可。
首先如何读入节点?我们直接scanf,能保证无论是空格还是换行每次都能成功读取一个节点。
如何创建树?首先要考虑树的结构,是标准指针定义形式还是数组模拟?我们用标准定义吧(数组模拟不太熟),其次想办法读取节点的数值(考虑sscanf),读取LR信息(考虑strchr获得','后LR的位置)获得LR信息后,每次createtree函数里面遍历LR,是L就走到左子树,R就右子树,直到走到尽头,赋值value为我们刚刚的数值。(需要考虑创建节点问题和重复问题)。
如何遍历节点?ez,直接用栈,吐出一个栈头就放入其左右子树,直到完毕(需要考虑左右子树是否创建问题,即value==-1否?还需考虑是否少输出了树(用length和len记录判断))
main:每次读入节点信息,若是遇到()则输出,遇到strlen(s)为零说明没读到,结束,否则将s传入createtree里面,正常创建节点,len++。

知识点

1.char * strchr(数组地址,待查字符);
返回待查字符的地址,想成arr数组名就好,或者返回NULL
2.sscanf(str,"模式如%d",地址),类似scanf,不过是从某个字符串str里面读入

纠错心路历程

初步写好程序后提交wa,初步考虑main函数主题逻辑问题。我们加一组数据
(2,)
(3,L) (9,RL)
(8,R) (6,LL) (7,LR) (12,RR) (4,LLL)
(13,LLR) (15,LRL) ()
显示not complete,而我们但凡触发not complete,一定是在三个if里面,所以我们依次删除三个if的printf("not complete"),已知第二个样例一定会触发not complete,我们只需看看哪次输出少一个not complete即可知是那个if逻辑出问题了!可见第二次少了一个not complete,即判断len和length那次.
即len不等于length了,该逻辑里面3个变量至少有一个错误赋值或初始化。先看len的逻辑。这是个全局变量。nb,我看到了,len只在flag等于1逻辑下初始化,但是显然其他逻辑若是成立,也应该初始化长度才对。尝试修改,在每个if后面初始化len。能成功过第三个样例。
是否ac?no!还是wa,马上反思,flag只在触发flag=1后初始化为零,有没有一种可能,我们在某种情况下flag=1,但是前面的某处if逻辑已经触发,导致flag=1未经过后面的if(flag1)导致flag未初始化??所以我们尝试把if(flag1)的逻辑提前,使得flag==1的话一定能够初始化,提交,终于ac

其他可能思路

//或者我们没必要建立一颗树,只需要判断能否构成一颗树,再根据其LR序号编码,排序输出?
//我们根据序号创建一个结构体,放入集合里面,再按LR顺序输出就可以
//那么关键就是判断是否能够形成一棵树
//判断重复简单,放入集合的时候就判断,如果相等(相等但值不一样,没说清楚)就not complete
//判断双亲节点是否缺失也简单,我们放好节点后,查找其双亲节点(n/2)是否存在即可
这个还未实现,应该简单得多。cy,学了重载运算符后有空实现下

代码

#include<iostream>
#include<queue>
#include<string>
#include<cstring>
//#define LOCAL

using namespace std;
const int mlen=260;
struct BiTree{//c++不需要typedef,struct完就是类型名
    int value;
    struct BiTree *lchild,*rchild;
    BiTree():value(-1),lchild(NULL),rchild(NULL){}
};
BiTree *root=new BiTree;
bool CreateTree(char *s);
bool TraverseTree(int *len_2,int *arr);
int main(){
    //读入s,如果长为2说明读入括号,则遍历树并输出,再初始化树
    //权且不管内存泄露问题
    char s[mlen];
    int num[mlen];
    bool flag=0;
    int len=0;
    #ifdef LOCAL
    freopen("uva.out","w",stdout);
    freopen("uva.in","r",stdin);
    #endif
    while(1){
        memset(s,0,mlen);
        scanf("%s",s);
        if(strlen(s)==0)return 0;
        if(strlen(s)==2){
            int length=0;
            if(flag==1){
                printf("not complete\n");
                len=0;flag=0;
            }
            else if(!TraverseTree(&length,num)){
                printf("not complete\n");
                len=0;
            }
            else if(len!=length){
                printf("not complete\n");
                len=0;
            }
            else {
                for(int i=0;i<length;i++){
                if(i)printf(" ");
                printf("%d",num[i]);
            }
            printf("\n");
            len=0;
        }
            root->value=-1;root->lchild=NULL;root->rchild=NULL;
        }
        else {
            bool a=CreateTree(s);
            if(!a)flag=1;
            len++;
        }
    }
    return 0;
}
bool CreateTree(char *s){//给出节点构造字符,构造对应节点,重复将输出0
    //(12345,LLRR)
    BiTree *TempTree=root;
    char *pos=strchr(s,',');
    int va;
    sscanf(s+1,"%d",&va);
    int length=strchr(s,')')-pos-1;
    if(length==0){
        if(root->value==-1){
            root->value=va;
            return 1;
        }
        else return 0;
    }
    for(int i=0;i<length;i++){
        if(*(pos+i+1)=='L'){
            if(TempTree->lchild==NULL)
                TempTree->lchild=new BiTree;
            TempTree=TempTree->lchild;
        }
        else{
            if(TempTree->rchild==NULL)
                TempTree->rchild=new BiTree;
            TempTree=TempTree->rchild;
        }
    }
    if(TempTree->value==-1){
        TempTree->value=va;
        return 1;
    }
    else return 0;
}
bool TraverseTree(int *len_2,int *arr){//给一个int数组地址,如果树是正确的,返回一并填充数组
    int i=0;
    queue <BiTree> que;
    que.push(*root);
    while(!que.empty()){
        BiTree temp=que.front();
        que.pop();
        if(temp.value==-1)return 0;
        else arr[i++]=temp.value;
        if(temp.lchild!=NULL)que.push(*(temp.lchild));
        if(temp.rchild!=NULL)que.push(*(temp.rchild));
    }
    *len_2=i;//刚好等于树的个数
    return 1;
}
posted @ 2025-08-14 21:36  hardestnut  阅读(15)  评论(0)    收藏  举报