百练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
",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;
}

 

原文地址:https://www.cnblogs.com/starryxsky/p/7106710.html