作为一个还没有系统学习数据结构知识的大一学生,简单谈一下通过这道题对二叉树产生的认识。
二叉树的一个节点中起码包含三个基础信息:节点权值、左子节点的地址(或编号)、右子节点的地址(或编号)。二叉树有三种实现方法:
1.第一类数组实现
在这种实现当中,对于编号为k的节点,其左子节点的编号为2*k,右子节点的编号为2*k + 1,另外确定根节点的编号为1.
毫无疑问,这种实现极易产生巨大的空间浪费,比如对于一个只有一条链的树,假设该树含有31个节点,存储这31个节点却需要开一个2^30的数组,因此此方法较少使用。
2.结构体+指针实现
设置结构体当中含有节点权值v,指向左子节点对应结构体的指针,指向右子节点对应结构体的指针,使用u->v访问权值,使用u->left访问左子节点,使用哪个u->right访问右子节点,这种实现大概是大二数据结构课程当中使用的方法,就不再赘述。
3.第二类数组实现
对于一棵有n个节点树,只需要开一个大小为n的数组,节点按照出现顺序依次编号,这么一来,每个节点的左右节点的编号就无法通过2*k,2*k+1的形式来直接确定了,这时就需要数组lch[maxn] , rch[maxn];其中lch[u]表示u节点的左子节点的编号,因此通过u = lch[u]就可以访问到u节点的左子节点,rch[u]的含义同理。另外,用value[u]表示编号为u节点的权值,如此一来,申请新节点的newnode函数与初始化的newtree函数写法就变得不同了,具体见代码。
二叉树的一个节点中起码包含三个基础信息:节点权值、左子节点的地址(或编号)、右子节点的地址(或编号)。二叉树有三种实现方法:
1.第一类数组实现
在这种实现当中,对于编号为k的节点,其左子节点的编号为2*k,右子节点的编号为2*k + 1,另外确定根节点的编号为1.
毫无疑问,这种实现极易产生巨大的空间浪费,比如对于一个只有一条链的树,假设该树含有31个节点,存储这31个节点却需要开一个2^30的数组,因此此方法较少使用。
2.结构体+指针实现
设置结构体当中含有节点权值v,指向左子节点对应结构体的指针,指向右子节点对应结构体的指针,使用u->v访问权值,使用u->left访问左子节点,使用哪个u->right访问右子节点,这种实现大概是大二数据结构课程当中使用的方法,就不再赘述。
3.第二类数组实现
对于一棵有n个节点树,只需要开一个大小为n的数组,节点按照出现顺序依次编号,这么一来,每个节点的左右节点的编号就无法通过2*k,2*k+1的形式来直接确定了,这时就需要数组lch[maxn] , rch[maxn];其中lch[u]表示u节点的左子节点的编号,因此通过u = lch[u]就可以访问到u节点的左子节点,rch[u]的含义同理。另外,用value[u]表示编号为u节点的权值,如此一来,申请新节点的newnode函数与初始化的newtree函数写法就变得不同了,具体见代码。
#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-8;
const int maxn = 300 ;
char s[5000];
bool failed;
bool have_value[maxn]; //针对本题要求,用来判断该节点是否被赋值,方便判断是否有节点被反复赋值或越过该节点为其子节点赋值
int lch[maxn], rch[maxn] , value[maxn];
const int root = 1 ;
int cnt; //按照出现顺序记录树中节点编号
vector<int> ans; //用于按顺序储存输出结果
void newtree() //初始化一颗新树,由于静态实现无法回收内存,因此顺便充当析构函数
{
lch[root] = rch[root] = 0;
have_value[root] = 0;
cnt = root;
}
int newnode() //建立新节点的函数,其中0相当于结构体中的空指针
{
int u = ++cnt;
lch[u] = rch[u] = 0;
have_value[u] = 0;
return u;
}
void addnode(int v , char * s) //建立新节点的过程
{
int n = strlen(s);
int u = root;
for(int i = 0; i<n;i++){
if(s[i] == 'L' ) {
if(lch[u] == 0)
lch[u] = newnode();
u = lch[u];
}
else if(s[i] == 'R'){
if(rch[u] == 0)
rch[u] = newnode();
u = rch[u];
}
}
if(have_value[u]) failed = true;
value[u] = v;
have_value[ u ] = 1;
}
bool read_input()
{
failed = false;
mem(lch,0); mem(rch,0);
mem(value,0); mem(have_value , 0);
newtree();
//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() //根据题目要求对树进行BFS
{
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(value[u]);
if(lch[u]) q.push(lch[u]);
if(rch[u]) q.push(rch[u]);
}
return true;
}
int main()
{
while(read_input()){
if(failed){
printf("not complete\n"); continue;
}
if(!BFS()) printf("not complete\n");
else{
int len = ans.size();
for(int i = 0; i<len; i++){
if(i!=len-1)
printf("%d ",ans[i]);
else
printf("%d\n",ans[i]);
}
}
}
return 0;
}