描述
输入
输入包含一棵树所形成的“伪满二叉树”的前序遍历。
第一行包含一个整数,表示结点的数目。
第二行包含所有结点。每个结点用两个字符表示,第一个字符表示结点的编号,第二个字符表示该结点为内部结点还是外部结点,内部结点为0,外部结点为1。结点之间用一个空格隔开。
数据保证所有结点的编号都为一个小写字母。
输出
输出包含这棵树的镜面映射的宽度优先遍历序列,只需要输出每个结点的编号,编号之间用一个空格隔开。
样例输入
样例输出
一棵树的镜面映射指的是对于树中的每个结点,都将其子结点反序。例如,对左边的树,镜面映射后变成右边这棵树。
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
解题思路:
这道题有以下几点注意的地方:
1.输入处理,用getchar()接收输入字符,用于滤掉换行与空格,用InputIn[]接收最终输入的字符
2.内外标识‘0’‘1’是字符形式!InputIn[]偶数位是真正的节点信息,奇数位是‘0‘或’1’
3.构建LCRS树时,将标识‘0’的节点指针存放到栈中,先插左边,再插右边,左右都满,回溯上级插右边!
4.利用BFS框架,购置一个队列,将父节点的所有子节点依次压入到队列中,镜像之后,利用栈将队列中的节点
倒序,每个非'$'key值的节点都将key值打印出来,ok大体思路如上!
#include<iostream> #include<stdio.h> #include<stack> #include<queue> using namespace std; const int MAX = 10000;//这棵树最多有10000个节点 char InputIn[2 * MAX];//这个数组存放MAX对(节点字母,0/1) char OutPut[MAX];//存放待输出的字符 //每一个点的数据结构 typedef struct _Node { char key; struct _Node *lchild; struct _Node *rchild; }Node; //定义全局变量栈 stack<Node *> s;//这个栈存放所有可能成为父节点的节点的指针 queue<Node *> q;//存放镜面对称后的节点序列 stack<Node *> t;//用于逆序 Node* CreateBiTree(int n) { Node* root = new Node; Node* father = new Node; root->key = InputIn[0]; root->lchild = root->rchild = NULL; s.push(root); for (int i = 2; i < n * 2; i += 2)//偶数个i意图是将数字滤掉,这样InputIn[i]一定是字母~,步长为2 { Node *temp = new Node; temp->key = InputIn[i]; temp->lchild = temp->rchild = NULL; father = s.top(); if (father->lchild == NULL)//当前父节点没有左节点 { father->lchild = temp; } else if (father->rchild == NULL)//当前父节点有左节点,但是没有右节点 { father->rchild = temp; } else//当前父节点左右子节点都有,退栈,寻找栈中右节点为空的节点 { while (s.top()->rchild != NULL) { s.pop(); } father = s.top();//s.top()->rchild == NULL father->rchild = temp; } if (InputIn[i + 1] == '0')//0说明这个点是内节点,不是叶子结点,可以成为父节点 { s.push(temp);//1说明这个点是叶子结点或者没有节点占位的$ } } return root; } void MirrorTrans(Node *root) { q.push(root); Node *father; while (!q.empty()) { father = q.front(); q.pop(); if (father->key != '$') { /*cout << father->key << " ";*/ printf("%c ", father->key); } if (father->lchild)//如果它有儿子节点 { Node *temp = father->lchild; while (temp) { t.push(temp);//将当前父节点的所有子节点都压入栈中 //q.push(temp); temp = temp->rchild; } } while (!t.empty()) { q.push(t.top()); t.pop(); } } } int main() { int n; char c; int i = 0; Node *root; scanf("%d", &n); getchar();//滤掉换行'\n' while ((c = getchar()) != '\n')//滤掉空格 { if (c != ' ') { InputIn[i++] = c; } } root = CreateBiTree(n); MirrorTrans(root); return 0; }