UVa 122 - Trees on the level
2016-07-10 20:26
288 查看
解题思路:
方法一:
题目意思很明白,就是一颗二叉树的层序遍历,那么我看到这道题立即产生的一种想法就是,根据题目输入对每个节点做一个映射,这颗二叉树的每个节点我们都用一个字符串来做它的唯一标识,那么比如某个父节点的字符串是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”.
接下来贴代码:
方法二:
这种方法就是刘汝佳那本书上所用的方法,先根据输入将二叉树建好,然后再用bfs层序遍历。
直接给代码吧:
方法三:
和方法二差不多,只不过这种方法是用数组来实现二叉树的,看了刘汝佳书上给出了这种思路于是就试着敲了一下,在方法二的基础上改了改,结果让我足足调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*外,整个程序就没有任何指针了。
接下来贴代码:
方法一:
题目意思很明白,就是一颗二叉树的层序遍历,那么我看到这道题立即产生的一种想法就是,根据题目输入对每个节点做一个映射,这颗二叉树的每个节点我们都用一个字符串来做它的唯一标识,那么比如某个父节点的字符串是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;
相关文章推荐
- 树及二叉树
- SDUT-数据结构实验之查找一:二叉排序树
- SDUT-3374 数据结构实验之查找二:平衡二叉树
- 7-19 并查集的算法
- 7-18 中序线索二叉树的算法
- 7-17 先序、中序和后序递归遍历算法
- 7-16 先序、中序和后序非递归遍历算法
- 7-15 层次遍历算法
- 7-14 构造哈夫曼树和哈夫曼编码的算法
- 7-13 构造二叉树的算法
- 7-12 二叉树的基本运算算法
- 7-11 将二叉树的顺序存储结构转换成二叉链存储结构
- 7-8 输出二叉树中值为x的节点的所有祖先
- 7-7 判断两棵二叉树是否相似
- 7-6 求二叉树中指定层次的节点个数
- 7-5 求二叉树中指定节点的层次
- 7-4 输出一棵给定二叉树的所有叶子节点
- 7-3 计算一棵给定二叉树的所有节点个数
- 7-2 孩子兄弟链存储结构下树的基本运算算法和求树t的高度
- 7-1 孩子链存储结构下树的基本运算算法和求树t的高度