二叉树的计数

6 篇文章 0 订阅
6 篇文章 0 订阅

##原题

###输入
第1行:二叉树的前序遍历顺序
第2行:后序遍历顺序

###输出
第1行:1个整数,表示所有可能的二叉树的数量

###样例输入1
ABC
CBA

###样例输出1
4

###样例输入2
ABCEDFGH
ECDBHGFA

###样例输出2
4

##分析
这道题也许你一拿到会觉得很难,甚至动起了爆搜的念头,但是这道题主要是弄清思路,其他就很简单了。

由于样例一的数据太简单了,所以我们分析样例二的数据。

###左子树?右子树?怎么找?
在先序中,左子树的根是紧跟在整棵树的根之后访问的,因此左子树的根在S1[1],即字符B.
在后序中,左子树的根是整个左子树最后一个被访问的,因此利用find函数,可以返回后序串S2中左子树根的位置:
T = S2.find(S1[1])
T也表示了左子树结点的个数. 因此:
左子树的后序串为:S2.substr(0, T) = BCED
左子树的先序串为:S1.substr(1, T) = ECDB
右子树的先序串为:S1.substr(T+2, S1.size()-T-1) = FGH
右子树的后序串为:S2.substr(T+1, S1.size()-T-1) = HGF

###左子树的递归处理
先序:BCED
后序:ECDB
####左子树
先序:CE
后序:EC
####右子树
先序:D
后序:D
左子树有2种形态,右子树有1种形态。根据乘法原理,整棵树有2种形态。

###右子树的递归处理
先序: FGH
后序: HGF
####左子子树:
先序:GH
后序:HG
####右子子树:空
左子子树有2种形态。因右子子树为空,左子子树可出现在右子子树的位置。这样右了树就可以有2*2=4种形态。

###总结
若当前树只有1个结点,则形态数为1.
否则根据前述方法划分左子树和右子树。若右子树为空,则总的形态数=左子树的形态数2.
若右子树不为空,则总的形态数=左子树的形态数
右子树的形态数。

思路得出来了,程序就好写了许多。

##源代码

#include<cstdio>
#include<cstring>
char a[101],b[101];
int count(int x,int y,int q,int w){
    if(w-q<0) return 2;
    if(w-q<2) return w-q+1;
    int p=strchr(b,a[q+1])-b;
    return count(x,p,q+1,q+1+p-x)*count(p+1,y-1,q+2+p-x,w);
}
int main()
{
    scanf("%s%s",a,b);
    int n=strlen(a);
    printf("%d",count(0,n-1,0,n-1));
}

是不是很简单啊。所以我们总结出,以后做题的时候一定要想好了再写程序,否则就会想这样臃肿:

#include<iostream>
#include<cstdio>
using namespace std;
int cnt=1,len1,len2;
void zhao(string s1,string s2)
{
    int l1=s1.length();
    int l2=s2.length();
    if(l1<=2||l2<=2)
    {
        if(s1[0]==s2[1]&&s1[1]==s2[0])
            cnt*=2;
        return;
    }
    else if(s1[1]==s2[l2-2])
    {
        cnt*=2;
        zhao(s1.substr(1,l1-1),s2.substr(0,l2-1));
    }
    else if(s1[1]!=s2[l2-2])
    {
        int o,p;
        for(int i=0;i<=len1;i++)
            if(s2[l2-2]==s1[i])
                o=i;
        for(int i=0;i<=len2;i++)
            if(s2[i]==s1[1])
                p=i;
        zhao(s1.substr(1,o-1),s2.substr(0,p+1));
        zhao(s1.substr(o,l1-o),s2.substr(p+1,l1-o));
    }
}
int main()
{
    string n,m;
    cin>>n;
    len1=n.length();
    cin>>m;
    len2=m.length();
    zhao(n,m);
    cout<<cnt;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值