Math 来自预订单和后订单遍历的k元树数

Math 来自预订单和后订单遍历的k元树数,math,tree,combinatorics,Math,Tree,Combinatorics,假设给出了前序和后序遍历和k。通过这些遍历有多少k元树 k元树是一种根树,每个顶点最多有k个子树。它取决于特定的遍历对。比如说 pre-order: a b c post-order: b c a 只描述一个可能的树(尽可能少,除非包含不一致的遍历对)。另一方面: pre-order: a b c post-order: c b a 描述2^(3-1)=4棵树(在所有场景中,最可能的情况是遍历有3个节点,k可以是任何内容),即4条3节点线 如果您想知道具有前序和后序遍历的可能二叉树的数量

假设给出了前序和后序遍历和k。通过这些遍历有多少k元树


k元树是一种根树,每个顶点最多有k个子树。

它取决于特定的遍历对。比如说

pre-order:  a b c
post-order: b c a
只描述一个可能的树(尽可能少,除非包含不一致的遍历对)。另一方面:

pre-order:  a b c
post-order: c b a

描述2^(3-1)=4棵树(在所有场景中,最可能的情况是遍历有3个节点,k可以是任何内容),即4条3节点线

如果您想知道具有前序和后序遍历的可能二叉树的数量,您应该首先绘制一棵可能的树。然后计算只有一个子节点的节点数。可能的树的总数为:2^(单个子节点的数量)

例如: pre:adbefgchij 邮政编码:dgfebijhca


我画了一棵树,它有3个子节点。因此,可能的树数为8。

首先通过DFS确定子树的对应范围,得到子树的数量,然后通过子树的组合进行求解

const int maxn = 30;
int C[maxn][maxn];
char pre[maxn],post[maxn];
int n,m;

void prepare()
{
    memset(C,0,sizeof(C));
    for(int i=0;i<maxn;i++)
    {
        C[i][0] = 1;
    }
    for(int i=1;i<maxn;i++)
    {
        for(int j=1;j<=i;j++)
        {
            C[i][j] = C[i-1][j-1] + C[i-1][j];
        }
    }
    return;
}

int dfs(int rs,int rt,int os,int ot)
{
    if(rs == rt) return 1;
    int son = 0,res = 1;
    int l = rs + 1,r = os;
    while(l <= rt)
    {
        while(r < ot)
        {
            if(pre[l] == post[r])
            {
                son++;
                break;
            }
            r++;
        }
        res *= dfs(l , l + r - os , os , r);
        l += r - os + 1;
        rs = l - 1;
        os = ++r;
    }
    return res * C[m][son];
}

int main()
{
    prepare();
    while(scanf("%d",&m) && m)
    {
        scanf("%s %s",pre,post);
        n = strlen(pre);
        printf("%d\n",dfs(0,n-1,0,n-1));
    }
    return 0;
}
const int maxn=30;
int C[maxn][maxn];
字符前[maxn],后[maxn];
int n,m;
无效准备()
{
memset(C,0,sizeof(C));

对于(int i=0;iWhy遍历与树的数量相关?@Henry:你知道,你不能用前序和后序遍历唯一地构造一棵树,但我想知道很多树都有这些遍历。你能举一个例子吗?两棵不同的树有相同的前序和后序遍历吗?@Henry:查看此链接: