uva 536 - Tree Recovery

这道题是一道很典型的树的构造,题目类型跟例题548相似。

这道题可以直接从字符串中提取,笔者因为对此方法并不熟悉,因此采用了先构造在输出的方法。

其方法是现将树构造成一个只有左枝的数,然后从中序字符串中得到左右树的长度,然后直接把左枝截断,成为右枝,如此可以轻松还原出树的原型来。


此方法的代码如下:

#include <iostream>
#include <algorithm>
#include <string>
#include <stack>


#include <cstring>
#include <cstdio>




using namespace std;


int len;


struct Tree
{
    Tree *left, *right;
    char flog;
    Tree():left(0), right(0), flog(0) {}
};
void KillTree(Tree* Root)
{
    if(Root)
    {
        KillTree(Root->left);
        KillTree(Root->right);
        delete Root;
    }
    //else return;
}
void OupTree(Tree* root){
    if(root){
        OupTree(root->left);
        OupTree(root->right);
        cout <<root->flog;
    }
}
Tree* MakeLeftTree(char* inp){
    if(* inp == 0)
        return 0;
    Tree* tr = new Tree;
    tr->flog = *inp;
    tr->left = MakeLeftTree(inp+1);
    return tr;
}


int FindChar(char* inp, char t){
    for(int i = 0; i < len; ++i){
        if(inp[i] == t)
            return i;
    }
}


void DealTree(char* inp, Tree* root){
    if(root == 0)        return ;
    int n = FindChar(inp, root->flog);
    inp[n] = 0;


    Tree* ptr1 = root;
    int sz = strlen(inp);
    for(int i = 0; i < sz; ++i)
        ptr1 = ptr1->left;
    root->right = ptr1->left;
    ptr1->left = 0;
    DealTree(inp, root->left);
    DealTree(inp+n+1, root->right);
}




int main(){
    char inp[30];
    Tree* TRoot;
    while(scanf("%s", inp) != -1){
        TRoot = MakeLeftTree(inp);
        scanf("%s", inp);
        len = strlen(inp);
        DealTree(inp, TRoot);
        OupTree(TRoot);
        cout <<endl;
        KillTree(TRoot);
    }
    return 0;
}


略作改进即可实现一边构建一边输出:

#include <iostream>
#include <algorithm>
#include <string>
#include <stack>


#include <cstring>
#include <cstdio>




using namespace std;


int len;


struct Tree
{
    Tree *left, *right;
    char flog;
    Tree():left(0), right(0), flog(0) {}
};
void KillTree(Tree* Root)
{
    if(Root)
    {
        KillTree(Root->left);
        KillTree(Root->right);
        delete Root;
    }
    //else return;
}
void OupTree(Tree* root){
    if(root){
        OupTree(root->left);
        OupTree(root->right);
        cout <<root->flog;
    }
}
Tree* MakeLeftTree(char* inp){
    if(* inp == 0)
        return 0;
    Tree* tr = new Tree;
    tr->flog = *inp;
    tr->left = MakeLeftTree(inp+1);
    return tr;
}


int FindChar(char* inp, char t){
    for(int i = 0; i < len; ++i){
        if(inp[i] == t)
            return i;
    }
}


void DealTree(char* inp, Tree* root){
    if(root == 0)        return ;
    int n = FindChar(inp, root->flog);
    inp[n] = 0;


    Tree* ptr1 = root;
    int sz = strlen(inp);
    for(int i = 0; i < sz; ++i)
        ptr1 = ptr1->left;
    root->right = ptr1->left;
    ptr1->left = 0;
    DealTree(inp, root->left);
    DealTree(inp+n+1, root->right);
    cout <<root->flog;
}




int main(){
    char inp[30];
    Tree* TRoot;
    while(scanf("%s", inp) != -1){
        TRoot = MakeLeftTree(inp);
        scanf("%s", inp);
        len = strlen(inp);
        DealTree(inp, TRoot);
        //OupTree(TRoot);
        cout <<endl;
        KillTree(TRoot);
    }
    return 0;
}


直接操纵字符串与上面方法相似,不再介绍,以下给出代码:


#include <iostream>
#include <algorithm>
#include <string>
#include <stack>

#include <cstring>
#include <cstdio>

using namespace std;


int FindChar(char* inp, char t){
    int len = strlen(inp);
    for(int i = 0; i < len; ++i){
        if(inp[i] == t)
            return i;
    }
}


void DealTree(char* inp, char* inp0, char root){
    if(root == 0)
        return ;
    int n = FindChar(inp, root);
    inp[n] = 0;
    int sz = strlen(inp);
    char rightroot = inp0[sz];
    inp0[sz] = 0;
    DealTree(inp, inp0+1, *inp0);
    DealTree(inp+n+1, inp0+sz+1, rightroot);
    cout <<root;
}

int main(){
    char inp[30], inp0[30];
    while(scanf("%s", inp0) != -1){
        scanf("%s", inp);
        DealTree(inp, inp0+1, inp0[0]);
        cout <<endl;
    }
    return 0;
}







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值