题意:
输入一棵二叉树,输入形式是给定一个结点值和一个字符串,如果字符串时L,则表示该节点在上一层相邻结点的左边,若是R,则表
示该节点在上一层相邻结点的右边,若没有字符串则表示该节点就是根节点,字符串和节点值用小括号括起来,并且相邻括号之间都
有空格隔开,空括号()则表示输入结束。然后要求你层次输出二叉树结点的值。注意:如果从根节点到某个叶节点的路径有的结点
没有给出,或者给出的超过一次,应当输出-1,结点的个数不应该超过256个。
input:
(11,LL) (7,LLL) (8,R) (5,) (4,L) (13,RL) (2,LLR) (1,RRR) (4,RR)()
(3,L) (4,R) ()
output:
5 4 8 11 13 4 7 2 1
-1
分析:
由于题意中并没有明确指出二叉树是一个满二叉树,而且结点数最大是256个,所以不能考虑将二叉树的结点作为编号放进数
组中,不能开那么大的数组,所以只能根据需要建立新的结点,然后再将结点组织成一棵树。首先需要定义一个node 的结构,
并对应整棵二叉树的树根root。然后是写个测试函数,测试根节点,左子树和右子树是否为空,再就是重头戏了,建树函数,由于
是递归建树,先从根节点开始,如果左子树为空,就建立结点,建树。右子树的操作一样,如果根节点为空,记录下来,并给它
赋值,相当于创建结点了。建树过程结束后,就是BFS层次遍历二叉树了,可以将二叉树的结点放进一个数组中去,边放边输,一
开始是一个根节点 ,然后输出一个结点,就把它的左右结点(如果存在)都放进去。过程详见代码,最后一步就是主函数的输入
了,本题的输入,是将其看成了一个字符串,并且巧妙的运用了sscanf()函数,详细见程序,下面上程序:
代码:
#include <bits/stdc++.h>
using namespace std;
typedef struct node //结点内容
{
int V;
node *L;
node *R;
}tree;
tree node[300];
tree *root;
int test(tree *root) //测试根节点,和左、右子节点是否为空
{
if(!root->V) //根节点为空
return 0;
int ans=0;
if(!root->L||test(root->L))
ans++;
if(!root->R||test(root->R))
ans++;
return ans==2; //左右子节点为空
}
int tree_size,complete; //tree_size编号,complete记录结点是否为空
int madetree(tree *root,char *str,int v) //建树过程
{
if(*str=='R')
{
if(!root->R) //右子树为空,建立结点
{
root->R=&node[++tree_size];
}
madetree(root->R,str+1,v); //建树
}
if(*str=='L')
{
if(!root->R)
{
root->R=&node[++tree_size];
}
madetree(root->L,str+1,v);
}
else
{
if(root->V)
complete=0; //表示根节点不为空
root->V=v; //根节点为空的时候就赋值。相当于创建新的结点
}
}
tree *Q[300];
void output(tree *root) //层次遍历二叉树
{
int _move=0,save=0;
Q[_move++]=root; //先将根节点放进去
cout <<root->V<<endl; //将根结点输出,然后将其左、右子节点放进数组
while(_move<save)//一层的结点个数恰好等于输出的左右子节点的个数,即一层输完
{
tree *now=Q[_move++];
if(now->L) //左子结点不为空
{
cout <<' '<<now->L->V<<endl; //输出左子结点的的值
Q[save++]=now->L;//并将其放入数组中
}
if(now->R)
{
cout <<' '<<now->R->V<<endl;
Q[save++]=now->R;
}
}
cout <<endl; //输完二叉树的一层换行
}
int main()
{
char buf[256],leaf[256];
int value;
complete=1; //初始化
root=&node[tree_size=0];
while(~scanf("%s",buf))
{
if(!strcmp(buf,"()"))
{
if(!complete||!test(root))
{
cout <<"no complete."<<endl;
}
else
{
output(root);
}
memset(node ,0,sizeof(node));
complete=1;
root=&node[tree_size=0];
}
else
{
sscanf(buf,"(%d,%s",&value,leaf); //强大的sscanf(),详细见小结
madetree(root,leaf,value);
}
}
return 0;
}
小结:本题十分重要,也是挺难得,这个题是我看着书写都感觉挺费劲的,要经常回来看这个题。
sscanf()函数的应用:
例子:
1. 常见用法。
char buf[512] = ;
sscanf("123456 ", "%s", buf);
printf("%s\n", buf);
结果为:123456
2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
sscanf("123456 ", "%4s", buf);
printf("%s\n", buf);
结果为:1234
3. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
sscanf("123456 abcdedf", "%[^ ]", buf);
printf("%s\n", buf);
结果为:123456
4. 取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
printf("%s\n", buf);
结果为:123456abcdedf
5. 取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);
printf("%s\n", buf);
结果为:123456abcdedf
6、给定一个字符串iios/12DDWDFF@122,获取 / 和 @ 之间的字符串,先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中
sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf);
printf("%s\n", buf);
结果为:12DDWDFF
7、给定一个字符串““hello, world”,仅保留world。(注意:“,”之后有一空格)
sscanf(“hello, world”, "%*s%s", buf);
printf("%s\n", buf);
结果为:world