您的位置:首页 > 其它

UVA 122 树的层次遍历

2016-10-28 16:10 260 查看
Description





Background

Trees are fundamental in many branches of computer science. Current state-of-the art parallel computers such as Thinking Machines' CM-5 are based on fat trees. Quad- and octal-trees are fundamental
to many algorithms in computer graphics.
This problem involves building and traversing binary trees.

The Problem

Given a sequence of binary trees, you are to write a program that prints a level-order traversal of each tree. In this problem each node of a binary tree contains a positive integer and all binary trees have
have fewer than 256 nodes.
In a level-order traversal of a tree, the data in all nodes at a given level are printed in left-to-right order and all nodes at level k are printed before all nodes at level k+1.
For example, a level order traversal of the tree



is: 5, 4, 8, 11, 13, 4, 7, 2, 1.
In this problem a binary tree is specified by a sequence of pairs (n,s) where n is the value at the node whose path from the root is given by the string s. A path is given
be a sequence of L's and R's where L indicates a left branch and R indicates a right branch. In the tree diagrammed above, the node containing 13 is specified by (13,RL), and the node containing 2 is specified by (2,LLR).
The root node is specified by (5,) where the empty string indicates the path from the root to itself. A binary tree is considered to be completely specifiedif every node on all root-to-node paths in the tree is given a value exactly once.

The Input

The input is a sequence of binary trees specified as described above. Each tree in a sequence consists of several pairs (n,s) as described above separated by whitespace. The last entry in each
tree is (). No whitespace appears between left and right parentheses.
All nodes contain a positive integer. Every tree in the input will consist of at least one node and no more than 256 nodes. Input is terminated by end-of-file.

The Output

For each completely specified binary tree in the input file, the level order traversal of that tree should be printed. If a tree is not completely specified, i.e., some node in the tree is NOT given a value
or a node is given a value more than once, then the string ``not complete'' should be printed.

Sample Input

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


Sample Output

5 4 8 11 13 4 7 2 1
not complete


第一次做关于的树的题,看了几遍就是不懂,硬是把 书上的代码敲了几遍,看网上的讲解,不过还不是很懂,不知道为什么可以这样去遍历一个树,链表指针没学好真的很伤啊。

借用一下被人的分析,以后自己也好看看。

分析:

由于题意中并没有明确指出二叉树是一个满二叉树,而且结点数最大是256个,所以不能考虑将二叉树的结点作为编号放进数

组中,不能开那么大的数组,所以只能根据需要建立新的结点,然后再将结点组织成一棵树。首先需要定义一个node 的结构,

并对应整棵二叉树的树根root。然后是写个测试函数,测试根节点,左子树和右子树是否为空,再就是重头戏了,建树函数,由于

是递归建树,先从根节点开始,如果左子树为空,就建立结点,建树。右子树的操作一样,如果根节点为空,记录下来,并给它

赋值,相当于创建结点了。建树过程结束后,就是BFS层次遍历二叉树了,可以将二叉树的结点放进一个数组中去,边放边输,一

开始是一个根节点 ,然后输出一个结点,就把它的左右结点(如果存在)都放进去。过程详见代码,最后一步就是主函数的输入

了,本题的输入,是将其看成了一个字符串,并且巧妙的运用了sscanf()函数,详细见程序,下面上程序:

附上敲了n次都 不理解的代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxn 300
using namespace std;
char s[maxn+10];//存储一个括号内的内容
//failed记录输入数据是否有误,n表示数的深度,ans存储树的顺序节点
int failed,n,ans[maxn];
typedef struct Tnode
{
int have_value;  //是否被赋值过
int v;  //节点值
struct Tnode *left,*right;
} Node;
Node * root; //二叉树的根节点

void remove_tree(Node *u)
{
if(u==NULL) return ;//提前判断比较稳妥
remove_tree(u->left);//递归释放左子树空间
remove_tree(u->right);//递归释放右子树空间
free(u);  //释放节点u本身的内存
}
//申请一个新的内存空间
Node *newnode()
{
Node* u=(Node*) malloc(sizeof(Node));//申请动态内存
if(u!=NULL) //若申请成功
{
u->have_value=0;     //显示的初始化为0,因为malloc申请内存时并不把他清零
u->left=u->right=NULL; //初始时没有左右儿子
}
return u;
}

void addnode(int v,char *s)//添加新的节点
{
int len=strlen(s);
Node*u=root;  //从根节点开始往下走
for(int i=0; i<len; i++)
if(s[i]=='L')
{
if(u->left==NULL) u->left=newnode();//若节点不存在,建立一个新的节点
u=u->left;//往左走
}
else if(s[i]=='R')
{
if(u->right==NULL) u->right=newnode();
u=u->right;//往右走
}//忽略其他情况,即最后那个右括号
if(u->have_value) failed=1;  //已经赋过值,表明输入有误
u->v=v;  //记录节点值
u->have_value=1; //标记
}

int read_input()
{
failed=0;  //初始化一定要为0
remove_tree(root);  //释放内存空间
root=newnode();  //一个新的节点,申请内存空间
for(;;)
{
if(scanf("%s",s)!=1) return 0; //录入一个括号内的内容
if(!strcmp(s,"()"))  break;  //遇到()结束
int v;
sscanf(&s[1],"%d",&v);  //读入节点值
addnode(v,strchr(s,',')+1); //传递节点值,逗号的位置
}
return 1;
}

int bfs()
{
n=0;
Node *q[maxn]; //存储节点值
q[0]=root;   //初始只有根节点
int front=0,rear=1;
while(front<rear)
{
Node *u=q[front++];
if(!u->have_value) return 0;//有节点没有被赋过值,鸟鸣输入有误
ans[n++]=u->v; //增加到输出序列的尾部
if(u->left!=NULL) q[rear++]=u->left;//左儿子存在。放进队列
if(u->right!=NULL) q[rear++]=u->right;//右儿子存在,放进队列
}
return 1;
}

int main()
{
while(read_input())//录入
{
if(failed||!bfs())   //构建的树不符合条件的
printf("not complete\n");
else
{
printf("%d",ans[0]);
for(int i=1; i<n; i++)
printf(" %d",ans[i]);
printf("\n");
}
}
return 0;
}


PS:

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 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: