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

本文介绍了一种处理树形结构的方法,包括如何构建树的伪满二叉树表示,实现树的镜像操作,并通过宽度优先遍历输出镜像树的节点序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

描述

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

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值