多叉树前序转后序

给定一颗多叉树,


该多叉树可以用一个后序遍历的字符串表示为4(0),5(0),1(2),6(0),2(1),7(0),8(0),9(0),10(0),3(4),0(3)

其中括号内的数字表示该节点的子节点数,比如0(3)表示节点03个子节点,而节点按照后序遍历的顺序排列。

给定一个类似的多叉树后序遍历的字符串,试写出一个程序输出其对应前序遍历的字符串。

如上述多叉树的前序遍历字符串为0,1,4,5,2,6,3,7,8,9,10

注意,在输出中不包含节点的子节点数。注意子节点是有顺序的,在输出中应保证子节点的顺序和后序遍历一致,比如在上例中,输出0,1,5,4,2,6,3,7,8,9,10是错误的。


输入:

输入多行数据,直到结束。每行数据包含一个多叉树的后序遍历的字符串。


输出:

对于每行输入数据,通过stdout,输出一行该多叉树的前序遍历的字符串


样例输入:

4(0),5(0),1(2),6(0),2(1),7(0),8(0),9(0),10(0),3(4),0(3)

1(0),3(0),4(0),2(2),0(2)

4(0),5(0),2(2),3(0),1(2),0(1)


样例输出:

0,1,4,5,2,6,3,7,8,9,10

0,1,2,3,4

0,1,2,4,5,3




分析:题目中给定的是后序遍历,所以会先读入子节点,最后读到父节点。当读到父节点时,应该“回过头来”从“已经读入”的子节点中取N个子节点,当做当前父节点的子节点。解题思路是顺序将节点放入队列,当读取到一个“有N个子节点”的节点时,应该从队列的尾部取出最后放进去的N个节点,做为当前节点的子节点,同时需要将当前节点放入队列,因为当前节点也有可能是后序节点的子节点。整个过程相当于“往前走2步,往后退1步”,会向前走,也会往后倒退。

代码如下:


#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <cassert>
#include <sstream>
#include <vector>
#include <stdlib.h>

using namespace std;

//从文件中读到的数据
struct InputData{
int value;//本节点的值
int childCnt;//本节点的孩子数
};

//树节点
struct TreeNode{
	int value;
	int childCnt;
	TreeNode **children;
public:
	TreeNode(){
		childCnt=0;
		children=NULL;
	}
};

//解析每行的数据
void fillData(string &lineBuffer,vector<InputData> &data){
	static InputData tmpID;	
	stringstream ss;

	data.clear();
	ss<<lineBuffer;

	while(!ss.eof()){
		ss>>tmpID.value;
		ss.clear();
		ss.get();
		ss>>tmpID.childCnt;
		ss.clear();
		ss.get();
		ss.get();
		data.push_back(tmpID);
	}
}

//打印vector,测试用
void printVector(vector<InputData> &data){
	vector<InputData>::iterator cur;
	for(cur=data.begin();cur!=data.end();++cur){
		cout<<cur->value<<"("<<cur->childCnt<<"),";
	}
}

//使用后序遍历生成树
TreeNode* buildTree(vector<InputData> &data){
	vector<InputData>::iterator cur;
	vector<TreeNode*> nodes;
	TreeNode* tmpNode;
	int brotherCnt=0;

	for(cur=data.begin();cur!=data.end();++cur){
		tmpNode=new TreeNode;
		tmpNode->value=cur->value;
		tmpNode->childCnt=cur->childCnt;

		//该节点有子节点
		if(cur->childCnt){
			tmpNode->children=new TreeNode*[cur->childCnt];
			//回退brotherCnt步,用于取该节点的子节点
			for(int i=0;i<cur->childCnt;++i){
				tmpNode->children[i]=nodes[i+brotherCnt-cur->childCnt];
			}
			//将队列下标回退brotherCnt步
			brotherCnt-=cur->childCnt;
		}
		
		//将当前节点放入队列,因为当期节点有可能是后序节点的子节点
		if(nodes.size()<=brotherCnt)
			nodes.push_back(tmpNode);
		else
			nodes[brotherCnt]=tmpNode;
		++brotherCnt;
	}

	return tmpNode;
}

//前序输出
int cnt;//当前输出到第几个数
int total;//总共需要输出多少个数
void printForward(TreeNode* root){
	cout<<root->value;
	
	//控制格式用
	++cnt;
	if(cnt<total)
		cout<<",";
	for(int i=0;i<root->childCnt;++i){
		if(root->children[i]->childCnt==0){
			cout<<root->children[i]->value;
	
			//控制格式用
			++cnt;
			if(cnt<total)
				cout<<",";
		}
		else{
			//递归打印
			printForward(root->children[i]);
		}
	}
}

int main(){
	fstream file;
	char sysInputFile[] = "c:/a.txt";
	file.open(sysInputFile);
	string lineBuffer;
	vector<InputData> data;
	int tmp;
	TreeNode* root;

	while (!file.eof()){
		   getline(file, lineBuffer);
		   if (lineBuffer.length() == 0)
			   continue; //ignore all empty lines
		   else{
			   fillData(lineBuffer,data);
			   cnt=0;
			   total=data.size();
			   //printVector(data);
			   root=buildTree(data);
			   printForward(root);
			   cout<<endl;
		   }
	}

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值