[luogu p1305] 新二叉树

传送门

新二叉树

题目描述

输入一串二叉树,输出其前序遍历。

输入输出格式

输入格式

第一行为二叉树的节点数 \(n\)。(\(1 \leq n \leq 26\))

后面 \(n\) 行,每一个字母为节点,后两个字母分别为其左右儿子。

空节点用 * 表示

输出格式

二叉树的前序遍历。

输入输出样例

输入样例 #1

6
abc
bdi
cj*
d**
i**
j**

输出样例 #1

abdicj

分析

这道题真的很简单了,首先找根,其次递归左右节点即可。

找根这方面有点技巧,首先根在这些读入的信息中一定只出现了1次,因为根节点不会作为其他节点的左右子节点出现,只会以根的形式出现。也就是只会出现在信息中的第一列一次。

除了根和星号以外,其他的字符一定出现了两次,因为信息要求任何节点都要表示出他的左右节点,哪怕是叶子节点也要表示出来两个星号。因此也会在信息的第一列出现一次。除此以外,除了根节点外,这个节点一定以子节点的形式出现在其他的信息中,也就是出现在信息的第二列或第三列一次。

这样就很简单了,异或是个好东西,同样的数异或的结果是0,这样我们就可以读入一个字符,如果这个字符s[i][j]不是星号,那么root ^= s[i][j]。两个同样的数不会影响结果,这样root的值就直接是根节点了。

然后是递归过程。首先递归函数中有一个参数ch,然后我们在信息中找到以ch为父亲节点的那一条信息,如果接下来的不是星号,则递归这条信息的第二个字符和第三个字符,也就是递归ch的左右节点。当然也可以把if(ch == '*') return ;放在递归的开头,也可以达到特判星号的目的。

代码

//忘加水印啦~qwq我忘记啥时候开始打的代码了,就不加啦~
#include <iostream>
#include <cstdio>

std :: string s[35];
int n;
char root;

void work(char ch) {
    if(ch == '*') return ;
    std :: cout << ch;
    for(int i = 1; i <= n; i++)
        if(s[i][0] == ch) {
            work(s[i][1]);
            work(s[i][2]);
        }
}

int main() {
    std :: cin >> n;
    for(int i = 1; i <= n; i++) {
        std :: cin >> s[i];
        for(int j = 0; j < 3; j++)
            if(s[i][j] != '*')
                root ^= s[i][j];
    }
    work(root);
    return 0;
}

评测结果

AC 100R31547308

posted @ 2020-03-09 10:44  dbxxx  阅读(250)  评论(0编辑  收藏  举报