树的镜面映射c++(含详细注释)

学校poj平台上的题,比较全面地考察了树的存储结构、相关函数及性质。

原题:

总时间限制: 

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

大体思路:

1.根据输入的二叉树前序序列重建二叉树

2.把二叉树转化成树(我这里用的是动态孩子存储,你也可以用左孩子右兄弟)

3.前序遍历树,把每一个节点的孩子都逆序,实现镜面映射

4.层序遍历输出树

代码:(注释掉的print函数是用来测试的)

#include<iostream>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
typedef struct BinNode {
	char data;
	BinNode* lchild;
	BinNode* rchild;
	BinNode() {
		data = '\0';
		lchild = NULL;
		rchild = NULL;
	}
}BinNode;
typedef struct CSNode {
	char data;
	vector<CSNode*> children;//动态数组存储孩子节点
	CSNode(int n) :data(n),children(vector<CSNode*>()){}
}CSNode;
CSNode* converse(BinNode* root) {//二叉树转成树(并返回对应树根节点)
	if (root == NULL) return NULL;//一个二叉树节点的左孩子如果有右孩子(对应树中的兄弟),就把
	vector<CSNode*> ve;//他左孩子所有的右孩子都作为他的孩子
	CSNode* t = new CSNode(root->data);
	BinNode* p = NULL;
	if (root->lchild && root->lchild->data != '$') {//左孩子非空
		p = root->lchild;
	}
	while (p && p->data!='$') {
		ve.push_back(converse(p));
		//if (p->rchild && p->rchild->data != '$')
			p = p->rchild;
	}
	t->children = ve;
	return t;
}
void printTree(CSNode* root) {//前序遍历打印树
	if (root == NULL)	return;
	cout << root->data << " ";
	for (int i = 0; i < root->children.size(); i++) {
		printTree(root->children[i]);
	}
}
void revert(CSNode* root) {//把给定节点的所有孩子节点逆序
	if (root == NULL)	return;
	int len = root->children.size();
	for (int i = 0; i < len / 2; i++) {
		CSNode* tmp = root->children[i];
		root->children[i] = root->children[len - i - 1];
		root->children[len - i - 1] = tmp;
	}
}
void mirror(CSNode* root) {//镜面映射树
	if (root == NULL)  return;
	revert(root);
	for (int i = 0; i < root->children.size(); i++) {
		mirror(root->children[i]);
	}
}
BinNode* rebuild(char x[],int num[],int n) {
	stack<BinNode*> s;
	BinNode* root = NULL;
	for (int i = 0; i < n; i++) {
		BinNode* r = new BinNode();
		if (i == 0)
			root = r;
		BinNode* cur = NULL;
		r->data = x[i];
		if (!s.empty()) {
			cur = s.top();
			if (cur->lchild == NULL) {
				cur->lchild = r;
				r->data = x[i];
			}	
			else if (cur->rchild == NULL) {
				cur->rchild = r;
				r->data = x[i];
			}	
			if (cur->lchild && cur->rchild)
				s.pop();
		}
		if (num[i] == 0 && x[i] != '$') {
			s.push(r);
		}
	}
	return root;
}
void bfsVisit(CSNode* root) {//层次遍历打印树
	if (!root)  return;
	queue<CSNode*> q;
	q.push(root);
	while (!q.empty()) {
		root = q.front();
		q.pop();
		cout << root->data << " ";
		for (int i = 0; i < root->children.size(); i++)
			q.push(root->children[i]);
	}
}
void bfsVisit(BinNode* root) {//二叉树层次遍历
	queue<BinNode*> q;
	BinNode* tmp = root;
	if (!tmp)  return;
	q.push(tmp);
	//cout << tmp->data << " ";//先压一个进去,否则进不去循环
	while (!q.empty()) {
		//if (tmp == q.front())  q.pop();
		tmp = q.front();
		q.pop();
		cout << tmp->data << " ";//出队列后再打印,否则最后一个元素没打印就出循环了
		if (tmp->lchild)//放在最后弹队列,防止中间出现队列最后一个元素出来后
			q.push(tmp->lchild);//其孩子没机会入队列就退出循环了
		if (tmp->rchild)
			q.push(tmp->rchild);
	}
}
int main() {
	int n;//节点数目
	cin >> n;
	char* x = new char[n]();
	int* num = new int[n]();
	for (int i = 0; i < n; i++) {
		cin >> x[i];
		cin >> num[i];
	}
	BinNode* root=rebuild(x,num,n);
	//bfsVisit(root); cout << endl;
	CSNode* t=converse(root);
	//printTree(t);
	mirror(t); 
	//printTree(t); cout << endl;
	bfsVisit(t);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值