百练4082:树的镜面映射

总时间限制:  1000ms          内存限制:  65536kB
描述

一棵树的镜面映射指的是对于树中的每个结点,都将其子结点反序。例如,对左边的树,镜面映射后变成右边这棵树

    a                             a
  / | \                         / |  b  c  f       ===>            f  c  b
   / \                           /   d   e                         e   d

我们在输入输出一棵树的时候,常常会把树转换成对应的二叉树,而且对该二叉树中只有单个子结点的分支结点补充一个虚子结点“$”,形成“伪满二叉树”。

例如,对下图左边的树,得到下图右边的伪满二叉树

  a                             a
  / | \                          /  b  c  f       ===>             b   $
   / \                         /   d   e                       $   c
                                 /                                 d   f
                               /                               $   e

然后对这棵二叉树进行前序遍历,如果是内部结点则标记为0,如果是叶结点则标记为1,而且虚结点也输出。

现在我们将一棵树以“伪满二叉树”的形式输入,要求输出这棵树的镜面映射的宽度优先遍历序列。

输入

输入包含一棵树所形成的“伪满二叉树”的前序遍历。

第一行包含一个整数,表示结点的数目。

第二行包含所有结点。每个结点用两个字符表示,第一个字符表示结点的编号,第二个字符表示该结点为内部结点还是外部结点,内部结点为0,外部结点为1。结点之间用一个空格隔开。

数据保证所有结点的编号都为一个小写字母。输出输出包含这棵树的镜面映射的宽度优先遍历序列,只需要输出每个结点的编号,编号之间用一个空格隔开。

样例输入

9
a0 b0 $1 c0 d0 $1 e1 f1 $1

样例输出

a f c b e d
#include <cstdio>
#include <stack>
#include <queue>
using namespace std;
struct node{
    char x;
    node *lchild;
    node *rchild;
}tree[1002];
int loc,n;
char temp[3];
node* create(){     //生成一个新的结点,并将其孩子结点置为NULL
        tree[loc].lchild = NULL;
        tree[loc].rchild = NULL;
        return &tree[loc++];
}
node *build(){      //该题输入为伪满二叉树的前序遍历,利用0、1标志来识别外结点和内结点
    scanf("%s",temp);
    node *p = create();
    p->x = temp[0];
    if(temp[1] == ‘0‘ && p->x != ‘$‘){
    //if(loc != n)    //因为已经给出01标志了,并且是伪满二叉树,所以这道题目的n(树的结点个数)信息冗余。
        p->lchild = build();
    //if(loc != n)
        p->rchild = build();
    }
    return p;
}
void Print(node *p){ //输出该树的镜像翻转
    stack<node *> s;
    queue<node *>Q;
    while(p != NULL){   //此处是关键,根据“左孩子右兄弟”的特点,一直向右遍历,将树同一层的结点都放在栈内
        //printf("push:%c.",p->x);
        if(p->x != ‘$‘)
        s.push(p);
        p = p->rchild;
    }
    while(!s.empty()){  //将栈内的结点依次弹出,压入队列,完成镜像翻转的功能
        Q.push(s.top());
        s.pop();
    }
    while(!Q.empty()){
        p = Q.front();
        Q.pop();
        printf("%c ",p->x);
        if(p->lchild != NULL){
            p = p->lchild;
            while(p != NULL){   //同理,上面是处理根节点的,因为那时队列还为空,这里是处理剩下的全部结点
                //printf("push:%c\n",p->x);
                if(p->x != ‘$‘)
                    s.push(p);
                p = p->rchild;
            }
            while(!s.empty()){
                Q.push(s.top());
                s.pop();
            }
        }
    }
    return;
}
void BFS(node *p){  //测试用的,实际上没调用
    queue<node *> Q;
    Q.push(p);
    while(!Q.empty()){
        p = Q.front();
        Q.pop();
        printf("%c ",p->x);
        if(p->lchild != NULL)
        Q.push(p->lchild);
        if(p->rchild != NULL)
        Q.push(p->rchild);
    }
}

int main(){
    loc = 0;
    scanf("%d",&n);
    node *root;
    root = build();
    Print(root);
    return 0;
}

 

时间: 2024-10-13 15:57:06

百练4082:树的镜面映射的相关文章

[OpenJudge] 百练2754 八皇后

八皇后 Description 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题. 对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8,其中bi为相应摆法中第i行皇后所处的列数.已经知道8皇后问题一共有92组解(即92个不同的皇后串).给出一个数b,要求输出第b个串.串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小. I

poj 百练 2765 八进制小数(精度问题)

2765:八进制小数 查看 提交 统计 提示 提问 总时间限制:  1000ms  内存限制:  65536kB 描述 八进制小数可以用十进制小数精确的表示.比如,八进制里面的0.75等于十进制里面的0.963125 (7/8 + 5/64).所有小数点后位数为n的八进制小数都可以表示成小数点后位数不多于3n的十进制小数. 你的任务是写一个程序,把(0, 1)中的八进制小数转化成十进制小数. 输入 输入包括若干八进制小数,每个小数占用一行.每个小数的形式是0.d1d2d3 ... dk,这里di

ACM/ICPC 之 递归(POJ2663-完全覆盖+POJ1057(百练2775)-旧式文件结构图)

POJ2663-完全覆盖 题解见首注释 //简单递推-三个米诺牌(3*2)为一个单位打草稿得出规律 //题意-3*n块方格能被1*2的米诺牌以多少种情况完全覆盖 //Memory 132K Time: 0 Ms #include<iostream> #include<cstring> #include<cstdio> using namespace std; int ans; //开始平铺 int Tiling(int n) { int sum = 0; if (n =

百练8216-分段函数-2016正式A题

百练 / 2016计算机学科夏令营上机考试 已经结束 题目 排名 状态 统计 提问 A:分段函数 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 编写程序,计算下列分段函数y=f(x)的值. y=-x+2.5; 0 <= x < 5 y=2-1.5(x-3)(x-3); 5 <= x < 10 y=x/2-1.5; 10 <= x < 20 输入 一个浮点数N,0 <= N < 20 输出 输出N对应的分段函数值:f

百练 1088 滑雪

“人人为我”的解法: dp[i][j]表示坐标为(i,j)的点开始下滑的最大长度. 则dp[i][j]为(i,j)周围四个点中比(i,j)低,且最大长度最大再加一的值 用结构体来储存一个点的坐标和高度,这样按高度从小到大排完序以后还不会丢失坐标的值 从小到大遍历所有的点,经过一个点(i,j)时,用递推公式求L(i,j). 一个小技巧: 将矩阵height四周的值赋值为INF,你可以想想这是滑雪场四周非常非常高的围墙. 这样就避免了数组越界的判断,而且不会影响正确结果(因为我们找的是滑雪场内部的最

百练6255-单词反转-2016正式B题

百练 / 2016计算机学科夏令营上机考试 已经结束 题目 排名 状态 统计 提问 B:单词翻转 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 输入一个句子(一行),将句子中的每一个单词翻转后输出. 输入 只有一行,为一个字符串,不超过500个字符.单词之间以空格隔开. 输出 翻转每一个单词后的字符串,单词之间的空格需与原文一致. 样例输入 hello world 样例输出 olleh dlrow 1 #include <iostream> 2 #i

百练OJ:2797最短前缀

刚开始找输入的退出方式死也没找着,原来这并不是个问题,上网看了一下有人直接这么写的 while( scanf( "%s", input[ temp ++]) != EOF ):输入完成后 通过输入一行Ctrl+Z再回车退出就行了,有人说用字典树,我不熟悉,直接暴力求解的,就是对于每一个输入的单词,从短到长把他的子串弄出来,依次判断是不是其他单词的子串,如果都不是,那就可以退出循环了:如果是,那证明这时的子串还不能代表本身,还要再长一些.用到的关键两个函数是strstr,判断是否是子串,

百练1088:滑雪 【DP】+【DFS】

总Time Limit: 1000ms Memory Limit: 65536kB Description Michael喜欢滑雪百这并不奇怪, 由于滑雪的确非常刺激.但是为了获得速度,滑的区域必须向下倾斜,并且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长的滑坡.区域由一个二维数组给出.数组的每一个数字代表点的高度.以下是一个 样例 1  2  3  4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 1

POJ百练—IP地址转换

#include<iostream> #include<cstdio> #include<cstring> using namespace std; int sign[9]; void change_to_8(int x) { int index=8; while(x) { if(x&1) { sign[index]=1; } x>>=1; index--; } } int main() { int a[4]; while(scanf("%