该多叉树可以用一个后序遍历的字符串表示为4(0),5(0),1(2),6(0),2(1),7(0),8(0),9(0),10(0),3(4),0(3)
其中括号内的数字表示该节点的子节点数,比如0(3)表示节点0有3个子节点,而节点按照后序遍历的顺序排列。
给定一个类似的多叉树后序遍历的字符串,试写出一个程序输出其对应前序遍历的字符串。
如上述多叉树的前序遍历字符串为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;
}