本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。
输入格式:
第一行给出正整数N(≤30),是树中结点的个数。随后两行,每行给出N个整数,分别对应后序遍历和中序遍历结果,数字间以空格分隔。题目保证输入正确对应一棵二叉树。
输出格式:
在一行中输出Preorder:以及该树的先序遍历结果。数字间有1个空格,行末不得有多余空格。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
Preorder: 4 1 3 2 6 5 7
参考代码:
#include<stdio.h>
#include<stdlib.h>
int a[30],b[30];//数组a存储后序遍历序列,数组b存储中序遍历序列
typedef struct treeNode *binTree;
struct treeNode{
int data;
binTree left;
binTree right;
};
void preorderTraversal(binTree BT); //先序遍历
binTree buildTree(int start,int end,int root);//建立二叉树
int main()
{
int n;
scanf("%d",&n);
int i;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<n;i++)
{
scanf("%d",&b[i]);
}
printf("Preorder:");
binTree head=buildTree(0,n-1,n-1);
preorderTraversal(head);
return 0;
}
void preorderTraversal(binTree BT)
{
if(BT)
{
printf(" %d",BT->data);
preorderTraversal(BT->left);
preorderTraversal(BT->right);
}
}
//start,end表示在中序遍历数组b中一棵树的起始位置和终止位置
//root表示在后序遍历数组a中根的位置
binTree buildTree(int start,int end,int root)
{
binTree bt=(binTree)malloc(sizeof(struct treeNode));
bt->data=a[root];
bt->left=NULL;
bt->right=NULL;
int i;
for(i=start;i<=end;i++)//遍历中序遍历序列的数组
{
if(a[root]==b[i]) //在中序遍历序列数组b中找到数的根
{
if(i!=start)//有左子树
{
bt->left=buildTree(start,i-1,root-(end-i)-1);
}
if(i!=end) //有右子树
{
bt->right=buildTree(i+1,end,root-1);
}
break;
}
}
return bt;
}
思路:
首先通过后序遍历序列和中序遍历序列建立一棵二叉树,再对二叉树进行前序遍历。
对二叉树进行前序遍历比较简单,采用递归或非递归算法均可(本题采用的是递归算法),这题主要是如何通过后序遍历和中序遍历建立一棵二叉数。
我们从图中可以看到后序遍历可以很容易的找到根节点是哪个数(后序遍历序列中一棵树的结尾位置),再通过遍历中序遍历序列找到中序遍历序列根节点的位置,可以找到左子树和右子树有哪些,再通过后序遍历确定左右子树的根节点,通过递归建立一棵完整的二叉树。
如何在后序遍历中确定左右子树根节点的位置?
左子树根节点位置root-(end-i)-1,树的根节点位置-右子树长度-1;
右子树根节点位置root-1,树的根节点位置-1。
总的来说:
后序遍历:确定一棵树的根节点是哪个;
中序遍历:确定一棵树的左右子树有哪些。