UVa 548 - Tree

这个题本来是看到书上有一个从前序遍历和中序遍历推后续遍历数列的一段代码,在此基础上改的,不过说实话还是蛮坑爹的,虽然最后写完AC代码比较短跑的时间也很短,但实际过程非常曲折,这可能与开始借鉴刘汝佳书上的那段代码有关系(大思路不合适),基本上是写一点调一点最后还WA了一次才改成功的 ~~

基本思路是用后序遍历和中序遍历模拟前序遍历过程然后算和,当然其中很多地方需要特殊标记和处理 ~~

总体来说,写的有点失败感觉,费的时间太多,唯一感觉收获比较大的是,将前中后序遍历,以及二叉树的递归及一些判断操作弄透彻了,也算不容易了 ~

注意:后序遍历中的最后一个元素为根元素,其在中序遍历中位置的左边元素为左子树,右边元素为右子树 ~

代码如下:

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<string>
using namespace std;
int* num_sort(int a[],int t)  // 在中序遍历中找后序遍历该元素的位置
{
    int i;
    for(i=0; a[i]!='\0'; i++)  
        if(a[i]==t)
            break;
    return &a[i];
}
int _min,kf;
int build(int n,int dep,int a[],int b[],int sum)
{
    if(n<=0)
    {
        if(_min>sum)  
        {
            _min=sum;
            kf=a[n];
        }
        else if(_min==sum && kf>a[n]) //和相同的情况下,比较元素的大小
            kf=a[n];
        return 1;
    }
    sum += b[n-dep-1];
    int p = num_sort(a,b[n-1-dep])-a;
    int flag = 0;
    if(!(!p && (n-p-1)))   // 难点之一,因为题中二叉树节点可能是只有左子树或是只有右子树,假如只有右子树((n-p-1)!=0),此时左子树(p为0)是不需要进行递归的,要是递归了,可能导致将其没有的左子树当成一个元素为0的叶子进行了min的判断,从而致使结果错误,在这里的调试和修改花费了大量的时间,太坑爹了!!!
         flag=build(p , dep , a , b , sum);
    ++dep; // 随着层数的加深,往右子树递归时记得该层的最后一个元素要比上一层最后一个元素提前一个
    if(!(p && !(n-p-1)) && !flag) //  注意flag的判断,如果是叶子节点,直接走完第一次递归就不用再进行第二次递归了,否则会导致错误,这里也调试修改了很久
         build(n-p-1 , dep , a+p+1 , b+p+1 , sum);
    return 0;
}
int main()
{
#ifdef test
    freopen("sample.txt","r",stdin);
#endif
    int a[10000+2],b[10000+2];
    while(1)
    {
        int flag = 1,ct,sum=0;
        _min=2147483647;
        char _c=' ';
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(ct=0 ; ; ct++) // 数字处理有点小麻烦,不过不是大问题
        {
            if( _c=='\n') //若是回车就跳出
                break;
            flag = scanf("%d",&a[ct]);
            if (flag==-1) break;
            _c=getchar();
        }
        if(flag==-1) break;
        for(int i=0; i<ct; i++)
            scanf( "%d" , &b[i] );
        build(ct , 0 , a , b , sum);
        printf( "%d\n" , kf );
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值