UVa 122 - Trees on the level

来源:互联网 发布:什么是淘宝登录密码 编辑:程序博客网 时间:2024/05/21 12:48

解题思路:
方法一:
题目意思很明白,就是一颗二叉树的层序遍历,那么我看到这道题立即产生的一种想法就是,根据题目输入对每个节点做一个映射,这颗二叉树的每个节点我们都用一个字符串来做它的唯一标识,那么比如某个父节点的字符串是str,那么它的两个孩子节点所对应的字符串就分别是str+”L”(左孩子)和str+”R”(右孩子),根据题目的输入我们可以让每个字符串映射一个整型的值,代表这个字符串所标识的那个节点所储存的内容(值)。然后我们用bfs层序遍历即可。(根节点所对应的字符串是空字符串,即str=”“是根节点的唯一标识。)
这道题的输入也比较复杂,我们需要从每个输入的字符串当中截取出我们所需要的整数值和它所对应的字符串,见下面几行代码。
int v;
sscanf(&s[1],”%d”,&v);
char *ss=strchr(s,’,’)+1;
char Mystr[maxn]=”“;
sscanf(ss, “%[^)]”,Mystr);
string Mystring=Mystr;
注释:比如输入的字符串是”(11,LL)”,那么&s[1] 指的就是”11,LL)”,sscanf(&s[1],”%d”,&v)意思是截取出字符串”11,LL)”中整数的值保存到变量v中,即v=11, strchr(s,’,’)意思是返回字符串s中字符’,’第一次出现的指针的位置,因此字符串ss=”LL)”,sscanf(ss, “%[^)]”,Mystr)意思是截取出字符串ss=”LL)”中不是字符’)’的字符保存到变量Mystr中,即Mystr=”LL”.
接下来贴代码:

#include <algorithm>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <ctype.h>#include <iostream>#include <map>#include <list>#include <queue>#include <set>#include <stack>#include <string>#include <vector>#define eps 1e-8#define INF 0x7fffffff#define PI acos(-1.0)#define seed 31//131,1313#define MAXV 50010#define maxn 300#define ALL(x) x.begin(),x.end()#define INS(x) inserter(x,x.begin())typedef long long LL;typedef unsigned long long ULL;using namespace std;int flag=1;char s[maxn];int longmax=0;bool read_input(map<string,int>& Mymap){  flag=1;  longmax=0;  while(1){    if(scanf("%s",s)!=1)      return  false;    if(!strcmp(s,"()"))      break;    int v;    sscanf(&s[1],"%d",&v);    char *ss=strchr(s,',')+1;    char Mystr[maxn]="";    sscanf(ss, "%[^)]",Mystr);    string Mystring=Mystr;    int len=strlen(Mystr);    if(len>longmax) longmax=len;    if(!Mymap.count(Mystring))        Mymap[Mystring]=v;    else flag=0;  }  return true;}bool bfs(vector<int>& ans,map<string,int>& Mymap){  queue<string>q;  ans.clear();  string a="";  q.push(a);  while(!q.empty()){    string b=q.front();    if(b.length()>longmax) break;    string c=b+"L";    string d=b+"R";    q.pop();    q.push(c);    q.push(d);    if(!Mymap.count(b)){      if(Mymap.count(c)||Mymap.count(d))        return false;    }    else ans.push_back(Mymap[b]);  }  return true;}int main(){    vector<int>ans;    while(1){        map<string,int>Mymap;        if(read_input(Mymap)==false) break;        if(!bfs(ans,Mymap))          flag=0;        if(flag==0) printf("not complete\n");        else{          for(int i=0;i<ans.size();i++){             if(i==ans.size()-1)                printf("%d\n",ans[i]);             else                printf("%d ",ans[i]);          }        }    }    return 0;}

方法二:
这种方法就是刘汝佳那本书上所用的方法,先根据输入将二叉树建好,然后再用bfs层序遍历。
直接给代码吧:

#include <algorithm>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <ctype.h>#include <iostream>#include <map>#include <list>#include <queue>#include <set>#include <stack>#include <string>#include <vector>#define eps 1e-8#define INF 0x7fffffff#define PI acos(-1.0)#define seed 31//131,1313#define MAXV 50010#define maxn 300#define ALL(x) x.begin(),x.end()#define INS(x) inserter(x,x.begin())typedef long long LL;typedef unsigned long long ULL;using namespace std;int flag=1;char s[maxn];struct Node{  bool have_value;  int v;  Node *Left,*Right;  Node():have_value(false),Left(NULL),Right(NULL){};};Node* root;Node *newnode(){  return new Node();}void remove_tree(Node* u) {   if(u == NULL) return; //提前判断比较稳妥   remove_tree(u->Left); //递归释放左子树的空间   remove_tree(u->Right); //递归释放右子树的空间   delete u; //调用u的析构函数并释放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)    flag=0;  u->v=v;  u->have_value=true;}bool read_input(){  flag=1;  remove_tree(root);  root=newnode();  while(1){    if(scanf("%s",s)!=1)      return  false;    if(!strcmp(s,"()"))      break;    int v;    sscanf(&s[1],"%d",&v);    addnode(v, strchr(s,',')+1);  }  return true;}bool bfs(vector<int>& ans){  queue<Node*>q;  ans.clear();  q.push(root);  while(!q.empty()){    Node *u=q.front();    q.pop();    if(!u->have_value)      return false;    ans.push_back(u->v);    if(u->Left!=NULL){      q.push(u->Left);    }    if(u->Right!=NULL){      q.push(u->Right);    }  }  return true;}int main(){    vector<int>ans;    while(read_input()){        if(!bfs(ans))          flag=0;        if(flag==0) printf("not complete\n");        else{          for(int i=0;i<ans.size();i++){             if(i==ans.size()-1)                printf("%d\n",ans[i]);             else                printf("%d ",ans[i]);          }        }    }    return 0;}

方法三:
和方法二差不多,只不过这种方法是用数组来实现二叉树的,看了刘汝佳书上给出了这种思路于是就试着敲了一下,在方法二的基础上改了改,结果让我足足调bug调了一上午,原因是他书上有句代码写错了呀!!!坑爹呀!!!
二叉树并不一定要用指针实现。接下来,把指针完全去掉。首先还是给每个结点编号,但不是按照从上到下从左到右的顺序,而是按照结点的生成顺序。用计数器cnt表示已存在的结点编号的最大值,因此new node函数需要改成这样:
const int root = 1;
int cnt;
void newtree() {
left[root] = right[root] = 0;
have_value[root] = false;
}
int newnode() {
int u = ++cnt;
left[u] = right[u] = 0;
have_value[u]=false; //刘汝佳的书在这块把u错写成root,大家注意
return u;
}
上面的newtree()是用来代替前面的“remove_tree(root)”和“root = newnode()”两条语句的:由于没有了动态内存的申请和释放,只需要重置结点计数器和根结点的左右子树了。接下来,把所有的Node*类型改成int类型,然后把结点结构中的成员变量改成全局数组(例如,u->left和u->right分别改成left[u]和right[u]),除了char*外,整个程序就没有任何指针了。

接下来贴代码:

#include <algorithm>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <ctype.h>#include <iostream>#include <map>#include <list>#include <queue>#include <set>#include <stack>#include <string>#include <vector>#define eps 1e-8#define INF 0x7fffffff#define PI acos(-1.0)#define seed 31//131,1313#define MAXV 50010#define maxn 300#define ALL(x) x.begin(),x.end()#define INS(x) inserter(x,x.begin())typedef long long LL;typedef unsigned long long ULL;using namespace std;int flag=1;char s[maxn];bool have_value[maxn];int Left[maxn],Right[maxn],V[maxn];const int root=1;int cnt;void newtree(){  Left[root]=Right[root]=0;  have_value[root]=false;  cnt=root;}int newnode(){  int u=++cnt;  Left[u]=Right[u]=0;  have_value[u]=false;  return u;}void addnode(int v,char *s){  int len=strlen(s);  int u=root; //从根结点开始往下走  for(int i=0;i<len;i++){    if(s[i]=='L'){      if(Left[u]==0)        Left[u]=newnode();      u=Left[u];    }    else if(s[i]=='R'){      if(Right[u]==0)        Right[u]=newnode();      u=Right[u];    }  }  if(have_value[u])    flag=0;  V[u]=v;  have_value[u]=true;}bool read_input(){  flag=1;  memset(Left,0,sizeof(Left));  memset(Right,0,sizeof(Right));  memset(V,0,sizeof(V));  newtree();  while(1){    if(scanf("%s",s)!=1)      return  false;    if(!strcmp(s,"()"))      break;    int v;    sscanf(&s[1],"%d",&v);    addnode(v, strchr(s,',')+1);  }  return true;}bool bfs(vector<int>& ans){  queue<int>q;  ans.clear();  q.push(root);  while(!q.empty()){    int u=q.front();    q.pop();    if(!have_value[u])      return false;    ans.push_back(V[u]);    if(Left[u]!=0){      q.push(Left[u]);    }    if(Right[u]!=0){      q.push(Right[u]);    }  }  return true;}int main(){    vector<int>ans;    while(read_input()){        if(!bfs(ans))          flag=0;        if(flag==0) printf("not complete\n");        else{          for(int i=0;i<ans.size();i++){             if(i==ans.size()-1)                printf("%d\n",ans[i]);             else                printf("%d ",ans[i]);          }        }    }    return 0;
0 0