UVA122
Posted torettorui
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA122相关的知识,希望对你有一定的参考价值。
这道题目是一道很好的内存管理的题目,
我的实现方式是直接使用数组来实现二叉树的动态构建,其中node[0]是根节点。
刘汝佳的两种实现方式:第一种是采用动态分配内存的方式(这种方式适合于所需要的节点数目不明确的情况)
第二种也是采用数组的方式,但是它将newtree() 和newnode() 写成了一种函数,这种程序结构更清晰一些,下面贴上三种不同版本的代码,分别进行分析
//这道题不好弄啊 //使用数组实现链式二叉树 #include<string> #include<cstring> #include<iostream> #include<cstdio> #include<queue> #include<vector> using namespace std; int Node[256],Left[256],Right[256]; //0代表树节点 bool error = false; int pos=0;//代表申请节点到了第几个 void print_tree() { for(int i = 0;i <= pos;i++) { printf("%d ",Node[i]); } printf(" "); for(int i = 0;i <= pos;i++) { printf("%d ",Left[i]); } printf(" "); for(int i = 0;i <= pos;i++) { printf("%d ",Right[i]); } printf(" "); } bool read_tree() { string pair; memset(Node,0,sizeof(Node)); memset(Left,0,sizeof(Left)); memset(Right,0,sizeof(Right)); error = false; pos = 0; while(cin >> pair) { //cout<<pair<<endl; if(pair == "()") { return true; } int x = pair.find(‘,‘); //printf("%d ",x); int index; sscanf(pair.substr(1,x-1).c_str(),"%d",&index); //printf("%d ",index); for(int i = x + 1,cur = 0;;i++) { //printf("%c ",pair[i]); if(pair[i]==‘)‘) { if(Node[cur]) error = true; Node[cur] = index; break; } else if(pair[i] == ‘L‘) { if(Left[cur] == 0) { Left[cur] = ++pos;//新申请的节点 } cur = Left[cur]; //printf("cur=%d ",cur); } else if(pair[i] == ‘R‘) { if(Right[cur] == 0) { Right[cur] = ++pos; } cur = Right[cur]; } } //print_tree(); } return false; } void level_order() { vector<int>Vector; queue<int>queue; queue.push(0); while(!queue.empty()) { int cur = queue.front(); queue.pop(); if(Node[cur] == 0)//如果有没有赋值的情况 { printf("not complete "); return; } else { if(Left[cur]) queue.push(Left[cur]); if(Right[cur]) queue.push(Right[cur]); Vector.push_back(Node[cur]); } } for(int i = 0;i < Vector.size();i++) { if(i) printf(" "); printf("%d",Vector[i]); } printf(" "); } int main() { #ifdef local freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout); #endif while(read_tree()) { if(error) { printf("not complete "); } else { level_order(); } } return 0; }
第一种是我写的代码,其中要注意的两个地方是:string的使用,刘汝佳使用的是数组,当我决定输入的那么pair的长度是不确定的,所以应该使用string。而且还有一点就是不可以使用sstream。另外,这道题目虽然在输入的过程中可以判断出是否合法,但是不可以中途断掉,只能使用一个数据结构error来保存是否有错误
第二种是刘汝佳的动态申请的版本
// UVa122 Trees on the level // Rujia Liu //此代码值得学习的地方,1》输入的处理 2》设立一个flag来表示本组数据有没有错误 3》将new node直接编写成一个函数。 //4》各个输出数据需要空一格,但最后一个数据没有空格的处理 #include<cstdio> #include<cstdlib> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn = 256 + 10; 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(); } bool failed; void addnode(int v, char* s) { int n = strlen(s); Node* u = root; for(int i = 0; i < n; i++)//建立一颗完整的树,u最后表示要插入数据的那个节点 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 = true;//如果之前已经有了数据,说明本组数据失败 u->v = v; u->have_value = true; } void remove_tree(Node* u) { if(u == NULL) return; remove_tree(u->left); remove_tree(u->right); delete u; } char s[maxn]; bool read_input() { failed = false; remove_tree(root);//释放原来的那棵树 root = newnode();//新创建一颗树 for(;;) { 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) {//将遍历的结果保存早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() { freopen("input.txt","r",stdin); freopen("out刘汝佳.txt","w",stdout); vector<int> ans;//这个也可以用队列实现,都可以无所谓 while(read_input()) { if(!bfs(ans)) failed = 1; if(failed) printf("not complete ");//如果本组数据输入失败,或者在层次遍历的时候,有的节点的数据没有输入 else { for(int i = 0; i < ans.size(); i++) { if(i != 0) printf(" ");//这个比first还好用哎,在i不等于0的前面加空格 printf("%d", ans[i]); } printf(" "); } } return 0; }
这段代码需要注意的地方就是释放内存的哪一个地方,需要先判断当前节点是否有值,否则会出错
第三段代码是使用了内存池技术的代码,这个想法非常的不错
// UVa122 Trees on the level // Rujia Liu #include<cstdio> #include<cstdlib> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn = 256 + 10; struct Node{ bool have_value; int v; Node* left, *right; Node():have_value(false),left(NULL),right(NULL){} }; Node* root; queue<Node*> freenodes; // 空闲列表 Node node[maxn]; // 内存池 //将节点都放入那个队列中去 void init() { for(int i = 0; i < maxn; i++) freenodes.push(&node[i]); } Node* newnode() { Node* u = freenodes.front(); u->left = u->right = NULL; u->have_value = false; // 重新初始化该结点 freenodes.pop(); return u; } void deletenode(Node* u) { freenodes.push(u); } bool failed; void addnode(int v, char* s) { int n = strlen(s); Node* u = root; for(int i = 0; i < n; 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 = true; u->v = v; u->have_value = true; } void remove_tree(Node* u) { if(u == NULL) return; remove_tree(u->left); remove_tree(u->right); deletenode(u); } char s[maxn]; bool read_input() { failed = false; remove_tree(root); root = newnode(); for(;;) { 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; init(); while(read_input()) { if(!bfs(ans)) failed = 1; if(failed) printf("not complete "); else { for(int i = 0; i < ans.size(); i++) { if(i != 0) printf(" "); printf("%d", ans[i]); } printf(" "); } } return 0; }
在newnode的时候,每次都是去queue的头节点来操作
以上是关于UVA122的主要内容,如果未能解决你的问题,请参考以下文章