NOJ1101Trees on the Level——二叉树+写法

74 篇文章 0 订阅

Trees on the Level

Time Limit(Common/Java):1000MS/3000MS          Memory Limit:65536KByte
Total Submit:350            Accepted:82

Description

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.
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 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 specified if every node on all root-to-node paths in the tree is given a value exactly once.

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. 

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

Source

UVa122


分析:可累死我了!!!

虽然是简单的二叉树,但是输入输出略复杂!

输入直接用字符串接收,然后处理:

while(scanf("%s",str) != EOF)
	{
		if(strcmp(str, "()") == 0)
分析出数字 和 路径(路径可以直接用整段字符串,当然也可以处理~)

sscanf(str+1, "%d", &x);
add(x, strchr(str, ',')+1);

sscanf(str+1, "%d", &x);
		add(x, strchr(str, ',')+1);

这里又见到了sscanf,第一次见到还是在写多线程下载器的时候,这个函数在字符串处理方面很厉害!

然后添加节点,注意这里根节点root每次输入时要重新初始化:root = new BTNode();  这里一开始初始化了,然后在每次输出结束后 要重新初始化,而且整棵树要释放内存,防止出错。输出最后没有空格!

插入节点时分析字符串的L,R,层层往下新建节点,这里节点的构造函数已经在BTNode类里面写好了。

输出就是按层遍历,也就是BFS。一个道理。要用到队列,这里就按照以前写过的按层遍历二叉树的写法。唯一不同的是这道题会有“no complete”的情况。这里略坑!也是卡主我WA1的主要原因,下面细细分析:

一开始判断“no complete”的方法是:不存在重复定义的节点 + 不存在已有节点的值为0的情况(初始化为0,每个节点会被赋值)。

但是WA1

几经探索,终于解决。初始化data应赋值-1 而不是0 。当然可以加一个判断标志,判断是否被赋值过了。


结语:关于二叉树,写法多样,可以用struct,class,我就沿用以前的风格用了class,把构造函数写好了,每次新建节点也比较方便。

此题的输入和初始化是重点!给出2种不同风格的代码。第一种是我的风格!

#include<iostream>
#include<string.h>
using namespace std;

class BTNode
{
public:
	int data;
	BTNode *lChild;
	BTNode *rChild;

	BTNode()
	{
		data = -1;
		lChild = NULL;
		rChild = NULL;
	}
};

BTNode *root;
bool fail = false; // 失败
int x;
char str[10];

void add(int x, char *str)
{
	int len = strlen(str);
	BTNode *t = root;
	for(int i=0;i<len-1;i++)
	{
		if(str[i] == 'L')
		{
			if(t->lChild == NULL) t->lChild = new BTNode();
			t = t->lChild;
		}
		if(str[i] == 'R')
		{
			if(t->rChild == NULL) t->rChild = new BTNode();
			t = t->rChild;
		}
	}
	if(t->data != -1) fail = true;
	t->data = x;
}

void destory(BTNode *t)
{
	if(t->lChild) destory(t->lChild);
	if(t->rChild) destory(t->rChild);
	delete t;
}

int ans[1000], num;
void bfs()
{
	num = 0;
	int front = 0, rear = 1;
	BTNode *p[1000];
	p[0] = root;
	while(front < rear)
	{
		BTNode * t = p[front++];
		if(t->data == -1) fail = true;
		ans[num++] = t->data;
		if(t->lChild) p[rear++] = t->lChild;
		if(t->rChild) p[rear++] = t->rChild;
	}
}

int main()
{
	root = new BTNode();
	while(scanf("%s",str) != EOF)
	{
		if(strcmp(str, "()") == 0)
		{
			bfs();
			if(fail == true) printf("not complete");
			else 
			{
				for(int i=0;i<num;i++)
				{
					if(i == 0) printf("%d",ans[0]);
					else printf(" %d",ans[i]);
				}
			}
			printf("\n");

			destory(root);
			fail = false;
			root = new BTNode();
			continue;
		}
		sscanf(str+1, "%d", &x);
		add(x, strchr(str, ',')+1);
	}

	return 0;
}



另一种用struct结构体的,类似:

#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  

const int MAXN = 256;  
  
typedef struct BTNode
{  
  int have_value;   //是否被赋值过  
  int v;            //节点值  
  struct BTNode* lChild, *rChild;   //左子树和右子树  

  BTNode()
  {
	  have_value = 0;
	  v = 0;
	  lChild = NULL; rChild = NULL;
  }
} Node;  
  
Node *root;  
int failed;  

//添加一个节点  
void addnode(int v, char* s) 
{  
  int n = strlen(s);  
  Node *cur = root;       //从根节点开始向下走  
  for(int i = 0; i < n; i++)  
    if(s[i] == 'L') {  
      //节点不存在则建立新节点  
      if(cur->lChild == NULL) cur->lChild = new Node();  
      //向左走  
      cur = cur->lChild;  
    }   
    else if(s[i] == 'R') {  
      if(cur->rChild == NULL) cur->rChild = new Node();  
      cur = cur->rChild;  
    } 
  
  
    //已经赋过值,表示输入有误  
    if(cur->have_value) failed = 1;  
    cur->v = v;  
    cur->have_value = 1;   //标记赋过值  
}  
  
//删除树  
void remove_tree(Node* u) {  
  if(u == NULL) return;  
  remove_tree(u->lChild);  
  remove_tree(u->rChild);  
  free(u);  
}  
  
//保存读入节点  
char s[MAXN + 10];  
  
//输入部分  
int read_input() {  
  failed = 0;  
    
  //防止内存泄露  
  remove_tree(root);  
  
  //创建根节点  
  root = new Node();  
  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 n = 0, ans[MAXN];  

int bfs() {  
  int front = 0, rear = 1;  
  Node* q[MAXN];  
  q[0] = root;  
  while(front < rear) {  
    Node* u = q[front++];  
    if(!u->have_value) return 0;  
    ans[n++] = u->v;  
    if(u->lChild != NULL) q[rear++] = u->lChild;  
    if(u->rChild != NULL) q[rear++] = u->rChild;  
  }  
  return 1;  
}  
  
int main() 
{  
  while(read_input()) {  
      
    if(!bfs()) failed = 1;  
    if(failed) printf("not complete\n");  
    else {  
      for(int i = 0; i < n; i++){  
          if(i==n-1){  
              printf("%d", ans[i]);  
          }  
          else{  
              printf("%d ", ans[i]);  
          }  
      }  
          
      printf("\n");  
    }  
    n = 0;  
  }  
  return 0;  
}  






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值