1. 题目描述:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=58
2. 解题思路:
a) 编写readin函数,专门用来读取数据。函数返回类型为bool,输入不合法时返回false。依题意,如果输入只有(),表示input终止,跳出循环并返回true
b) 编写名为Node的结构体。结构体中包含input中括号左侧的结值、判断结点是否被赋值的bool类型的值,和类型为Node *的左右子结点。由于二叉树是递归定义的,其左右子结点类型都是“指向结类型的指针”,因此左右子结点的类型都是Node *
c) 建立全局变量failed,记录是否有从根到某个叶结的路径上有的结没有在输入中给出或值给出超过一次的情况
d) 建立函数addnode:按照移动序列走,目标不存在时调用newnode函数来创造新结点,判断结点是否已被赋值(如果已经被赋过值,将failed值改为true),并将结点值赋给对应的结点
e) bfs找结点,使用队列:初始时只有一个根结点,然后每次取出一个结点,把它的左右子结点(如果存在)放进队列中,用vector保存结点的值
3.
#include <vector> #include <cstring> #include <queue> #include <cstdio> #include <iostream> using namespace std; const int maxn=256+10; char s[maxn]; bool failed; struct Node{ int v; //结点值 bool have_value; //是否被赋过值 Node *left,*right; }; Node *root; //二叉树的根结点 Node* newnode(){ return new Node(); //每建立一个新的Node,用new运算符申请内存 } void addnode(int v,char* s){ Node* u=root; //从根结点开始往下走 int n=strlen(s); 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; //不要忘记做标记,判断是否已赋过值 } bool readin(){ failed=false; 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; 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(){ while(1){ if(!readin()) break; vector<int> ans; if(!failed&&bfs(ans)){ int len=ans.size(); for(int i=0;i<len;i++) printf("%d%c",ans[i],i==len-1?'\n':' '); } else{ printf("not complete"); } } return 0; }