题意 :输入一棵二叉树,你的任务是按从上到下、从左到右的顺序输出各个结点的值。每个结 点都按照从根结点到它的移动序列给出(L表示左,R表示右)。在输入中,每个结点的左 括号和右括号之间没有空格,相邻结点之间用一个空格隔开。每棵树的输入用一对空括 号“()”结束(这对括号本身不代表一个结点),注意,如果从根到某个叶结点的路径上有的结点没有在输入中给出,或者给出超过一 次,应当输出not complete。结点个数不超过256。
分析 : 如果使用数组建树的话,256个结点看着不多,但是如果全部的节点都连成一条线的话数组是不足以存储的,所以采用指针链表的方式存储,动态建树。这道题还需要输出无法建造出树的情况,而一般的动态建树都是从根结点自上而下的建立,判断就变得些许麻烦了。如果从输入考虑的话,可以先按某种方式排序,使得输入和建树顺序是一致的,那么判断就方便了,这里紫书用了一个更简便的方法,直接在根节点的结构里面定义一个布尔数组来判断这个节点是否已经赋值,那么在建树的过程当中,不管当前这个点是否合法(其父节点已经存在),先全部动态分配内存建立起来,判断此树是否合法的工作只要在层序遍历时判断每个节点的布尔值即可。层序遍历则可以想象成BFS广搜在搜索解答树的过程,利用队列即可完成。
瞎 :
① strchr(char *, char) 即找到char *数组中第一次出现char的位置,类似于string::find_first_of()
②题目输入结束的条件是EOF,这时候不要轻易用while(1){...},超时也有可能是这样的输入导致,考虑将输入变成函数 bool read(){..}然后while(read()){...}来解决。
#include<bits/stdc++.h> using namespace std; struct Node { bool Have_val; int val; Node * Left, * Right; Node():Have_val(false),Left(NULL),Right(NULL){} }; ]; Node * root; bool Failed; Node * newnode() { return new Node(); } inline void Addnode(int num, char * s) { int len = strlen(s); Node * u = root; ; 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_val) Failed = true; u->val = num; u->Have_val = true; } ]; ; inline void bfs() { queue<Node *> q; q.push(root); while(!q.empty()){ Node * temp = q.front(); q.pop(); if(!temp->Have_val){ Failed = true; return ; } ans[top++] = temp->val; if(temp->Left!=NULL) q.push(temp->Left); if(temp->Right!=NULL) q.push(temp->Right); } } inline void destroy(Node * u) { if(u==NULL) return ; destroy(u->Left); destroy(u->Right); delete u; } bool read() { Failed = false; destroy(root); root = newnode(); while(true){ ) return false; if(!strcmp(s, "()")) break; int v; sscanf(&s[], "%d", &v); Addnode(v, strchr(s, ); } return true; } int main(void) { while(read()){ top = ; bfs(); if(Failed) puts("not complete"); else{ ; i<top-; i++) printf("%d ", ans[i]); printf(]); } } ; }