【15分】E. DS森林叶子编码

题目描述
给定一组森林,编写程序生成对应的二叉树,输出这颗二叉树叶结点对应的二进制编码.规定二叉树的左边由0表示,二叉树的右边由1表示。


输入
输入:

N B 表示N个树,每结点最多B个分支

第2行至第N+1行,每个树的先序遍历


输出
每行表示一个叶结点对应的二进制编码.

输入样例1

3 3
A B 0 0 0 C 0 0 0 D 0 0 0
E F 0 0 0 0 0
G H 0 0 0 I J 0 0 0 0 0 0

输出样例1

0 1 1
1 0
1 1 0 1 0

思路

创建四个类,分别为普通节点Node,二叉结点BiNode,普通树Tree,二叉树BiTree。

循环N次,每次先序遍历创建一棵普通树,然后将这棵普通树转换成一棵二叉树。

注意:转换的时候有一个易错点,我在这里卡了好久!!!

我们再来复习一下普通树转二叉树的核心步骤:
将树的根节点的第一个子节点作为二叉树根节点的左指针,若该子节点存在兄弟节点,则将该子节点的第一个兄弟节点(方向从左往右)作为该子节点的右指针,并递归进行下一步

我当时做错的原因就是把根节点的第一个子节点理解错了,其实更准确的表达是根节点的第一个非空子节点。因此不是p->firstchild = change(T->child[0]),而是找到一个非空的子节点cnt,然后p->firstchild = change(T->child[cnt])

接下来就是把所有已经转换好的二叉树合并了,如果是第一棵二叉树就直接赋值,剩下的二叉树就并为上一棵二叉树的根节点的右子树。


代码

#include <iostream>
#include <cstring>
using namespace std;

int B;
int N;

class Node
{
public:
    char data;
    Node **child;
    

    Node()
    {
        child = new Node*[B];
    }
};

class BiNode
{
public:
    char data;
    BiNode *firstchild;
    BiNode *next;
};


class Tree
{
public:
    Node *root;
    string str;
    int pos;

    Tree(string s)
    {
        str.assign(s);
        pos = 0;
        root = creat();
        
    }

    Node* creat()
    {
        if(str[pos] == '0')
        {
            pos ++;
            return NULL;
        }

        Node *p = new Node;
        p->data = str[pos];
        pos ++;
        for(int i = 0;i < B;i ++)
        {
            p->child[i] = creat();
        }
        return p;
    }

    BiNode* change(Node *T)
    {
        BiNode *p = NULL;
        if(T)
        {
            p = new BiNode;
            p->data = T->data;
            int cnt = 0;
            // 易错的地方!!!!
            while(!T->child[cnt] && cnt < B) cnt ++;
            if(cnt == B) p->firstchild = change(NULL);
            else p->firstchild = change(T->child[cnt]);
            if(p->firstchild)
            {
                BiNode *q = p->firstchild;
                
                for(int i = cnt+1;i < B;i ++)
                {
                    q->next = change(T->child[i]);
                    if(q->next) q = q->next;
                }
            }
        }
        return p;
    }
};

class BiTree
{
public:
    BiNode *root;

    BiTree(Tree T)
    {
        root = T.change(T.root);
    }
};

void preOrder(BiNode *p, string s)
{
    if(!p->firstchild && !p->next) 
    {
        for(int i = 0;i < s.length();i ++)
        {
            if(i) cout << " ";
            cout << s[i];
        }
        cout << endl;
    }
    if(p->firstchild) preOrder(p->firstchild, s + '0');
    if(p->next) preOrder(p->next, s + '1');
}


int main()
{
    cin >> N >> B;
    BiNode *p;
    for(int i = 0;i < N;i ++)
    {
        string s;
        char op;
        while(cin >> op)
        {
            s += op;
            if(getchar() == '\n') break;
        }
        Tree mytree(s);
        BiTree t(mytree);
        if(i == 0)
        {
            p = t.root;
        }
        else
        {
            BiNode *q = p;
            while(q->next) q = q->next;
            q->next = t.root;
        }
    }
    preOrder(p,"");
    
    return 0;
}
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叫我胡萝北

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值