Uva122 Trees on the level 二叉树的数组实现

      作为一个还没有系统学习数据结构知识的大一学生,简单谈一下通过这道题对二叉树产生的认识。
      二叉树的一个节点中起码包含三个基础信息:节点权值、左子节点的地址(或编号)、右子节点的地址(或编号)。二叉树有三种实现方法:
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;
}

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值