题目描述:
输入某二叉树的前序遍历和中序遍历的结果,
请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。
思路
根据前序遍历的数组,arr[0]为根节点,在中序遍历中找到值等于arr[0]的位置index,则index的左边为此节点的左子树,右边为此节点的右子树。于是递归构建该节点的左右子树。
需要考虑的测试用例
1)一个结点的数
2)只有左子树的树
3)只有右子树的树
4)普通的树
5)特殊输入
/*
输入:
输入可能包含多个测试样例,对于每个测试案例,
输入的第一行为一个整数n(1<=n<=1000):代表二叉树的节点个数。
输入的第二行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的前序遍历序列。
输入的第三行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的中序遍历序列。
输出:
对应每个测试案例,输出一行:
如果题目中所给的前序和中序遍历序列能构成一棵二叉树,则输出n个整数,代表二叉树的后序遍历序列,每个元素后面都有空格。
如果题目中所给的前序和中序遍历序列不能构成一棵二叉树,则输出”No”。
样例输入:
8
1 2 4 7 3 5 6 8
4 7 2 1 5 3 8 6
8
1 2 4 7 3 5 6 8
4 1 2 7 5 3 8 6
样例输出:
7 4 2 5 8 6 3 1 No
*/
#include<stdio.h>
#include<stdlib.h>
struct TreeNode{
int mValue;
struct TreeNode *lchild;
struct TreeNode *rchild;
};
bool canRebuild;
/*
函数的功能:根据树的前序遍历、中序遍历来重构二叉树。
参数的说明
@param pRoot:即将重构的Tree的头结点的指针。
@param n:节点的个数
@param preTraversal :前序遍历的数组。
@param inTraversal:后序遍历的数组
*/
void rebuildBTree(TreeNode **pRoot,int len,int *preTraversal,int *inTraversal){
if(preTraversal==NULL||inTraversal==NULL) {
canRebuild=false;
return ;
}
//
if(len<1){
return;
}
//在中序遍历中找到前序遍历的头结点的左右子结点
int index=-1;
for(int i=0;i<len;i++){
if(preTraversal[0]==inTraversal[i]){
index=i;
break;
}
}
if(index==-1){//这种情况就是没有找到当前根结点在中序遍历的位置。因此不能重构
canRebuild=false;
return;
}
//找到了之后就开始构建此结点
//为当前结点分配空间
(*pRoot)=(TreeNode *)malloc(sizeof(struct TreeNode));
if((*pRoot)==NULL){
exit(EXIT_FAILURE);
}
(*pRoot)->mValue=preTraversal[0];
(*pRoot)->lchild=NULL;
(*pRoot)->rchild=NULL;
//接下来开始构建该结点的左右子树。
rebuildBTree(&((*pRoot)->lchild),index,preTraversal+1,inTraversal);
rebuildBTree(&((*pRoot)->rchild),len-index-1,preTraversal+index+1,inTraversal+index+1);
}
//按后序遍历输出二叉树
void postTraversal(TreeNode *pRoot){
if(pRoot==NULL){
return;
}
if(pRoot->lchild!=NULL){
postTraversal(pRoot->lchild);
}
if(pRoot->rchild!=NULL){
postTraversal(pRoot->rchild);
}
printf("%d ",pRoot->mValue);
}
void destoryBTree(TreeNode* pRoot){
if(pRoot==NULL){
return;
}
destoryBTree(pRoot->lchild);
destoryBTree(pRoot->rchild);
if(pRoot->lchild==NULL||pRoot->rchild==NULL){
free(pRoot);
pRoot=NULL;
}
return;
}
int main(void){
int n;
while(scanf("%d",&n)&&n>0){
int *preTraversal=(int *)malloc(n*sizeof(int));
int *inTraversal=(int *)malloc(n*sizeof(int));
if(preTraversal==NULL||inTraversal==NULL){
exit(EXIT_FAILURE);
}
for(int i=0;i<n;i++){
scanf("%d",preTraversal+i);
}
for(int i=0;i<n;i++){
scanf("%d",inTraversal+i);
}
//重构二叉树
TreeNode *pRoot;
bool canRebuild=true;
rebuildBTree(&pRoot,n,preTraversal,inTraversal) ;
if(canRebuild){
//按后序遍历输出
postTraversal(pRoot);
printf("\n");
}
else{
printf("No\n");
}
//最后销毁二叉树
destoryBTree(pRoot);
free(preTraversal);
preTraversal=NULL;
free(inTraversal);
inTraversal=NULL;
}
return 0;
}
今天和同学聊起这个题,说不知道用Java如何来重建二叉树,于是就写了下,代码如下,2016年8月23日16:20:20
public class RebuildTree2 {
private static boolean canRebuild = true;
private static int[] postOrder ;
private static int indexPost = 0;
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre==null||in==null||pre.length!=in.length){
return null;
}
TreeNode head = rebuildHelper(pre,in,pre.length);
if(!canRebuild){//不能重建
return null;
}
return head;
}
private TreeNode rebuildHelper(int[] pre, int[] in, int len) {
if(pre==null||in==null||len<1){
//canRebuild = false;
return null;
}
int val = pre[0];//根节点
//在中序遍历中找到头结点出现的位置
int index = -1;
for(int i=0;i<len;i++){
if(in[i]==val){
index = i;
break;
}
}
if(index==-1){//在中序遍历中没有找到根节点,因此不能重建
canRebuild = false;
return null;
}
//构建当前根节点
TreeNode head = new TreeNode(val);
//接着开始构建根节点的左右子树
//左子树
//先进行数组的拷贝
int len1 = index ;
int[] preNew = new int[len1];
int[] inNew = new int[len1];
for(int i=0;i<len1;i++){
preNew[i] = pre[1+i];
inNew[i] = in[i];
}
head.left = rebuildHelper(preNew, inNew,len1);
//检查左子树是否能够重建
if(!canRebuild){
return null;
}
//右子树
//先进行数组的拷贝
int len2 = len-index-1;
int[] preNew2 = new int[len2];
int[] inNew2 = new int[len2];
for(int i=0;i<len2;i++){
preNew2[i] = pre[index+1+i];
inNew2[i] = in[index+1+i];
}
head.right = rebuildHelper(preNew2, inNew2,len2);
return head;
}
public static void main(String[] args){
int len = 7;
int[] pre = {1,2,3,4,5,6,7};
int[] in = {3,2,4,1,6,5,7};
postOrder = new int[len];
RebuildTree2 bt = new RebuildTree2();
TreeNode head = bt.reConstructBinaryTree(pre,in);
System.out.println(head.val);
//后序遍历
bt.postOrder(head);
for(int i=0;i<len;i++){
System.out.print(postOrder[i]+" ");
}
}
private void postOrder(TreeNode head) {
if(head==null){
return ;
}
if(head.left!=null){
postOrder(head.left);
}
if(head.right!=null){
postOrder(head.right);
}
postOrder[indexPost] = head.val;
indexPost++;
//System.out.print(head.val+" ");
}
}