0
点赞
收藏
分享

微信扫一扫

POJ4082树的镜面转换--左子右兄数与树的转换(一)


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



    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;
}



举报

相关推荐

0 条评论