一棵树的镜面映射指的是对于树中的每个结点,都将其子结点反序。例如,对左边的树,镜面映射后变成右边这棵树。
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;
}