练习4.1 根据后序和中序遍历输出先序遍历 (25分)
本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。
输入格式:
第一行给出正整数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
先讲讲思路:
用递归做的。
在后序遍历的最后一个数字4是根结点,在中序遍历中找到根结点4,4左边的序列1 2 3共3个结点是左子树的中序遍历,4右边的序列5 6 7共3个结点是右子树的中序遍历。在后序遍历中前3个结点2 3 1是左子树的后序遍历,紧接着的3个结点5 7 6是右子树的后序遍历。
即变成了两个子树的后序遍历和中序遍历序列以及根结点。
左子树的后序遍历为2 3 1
左子树的中序遍历为1 2 3
右子树的后序遍历为5 7 6
右子树的中序遍历为5 6 7
根结点为4
按同样的步骤可以将左子树也分成左子树、右子树和根这3部分,右子树也可以分成左子树、右子树和根这3部分。
C语言实现:
#include <stdio.h>
#include<stdlib.h>
void preorder(int po[], int mo[], int n);
int main()
{
int n;
scanf("%d\n", &n);
int * postorder;
postorder = (int *)malloc(30 * sizeof(int));
int * midorder;
midorder = (int *)malloc(30 * sizeof(int));
int i;
for (i = 0; i < n; i++)
{
scanf("%d", &(postorder[i]));
}
for (i = 0; i < n; i++)
{
scanf("%d", &(midorder[i]));
}
printf("Preorder:");
preorder(postorder, midorder, n);
return 0;
}
void preorder(int po[], int mo[], int n)
{
if (po != NULL)
{
printf(" %d", po[n - 1]);
if (n > 1)
{
//左子树的中序遍历和后序遍历
int i = 0;
int * ml;
ml = (int *)malloc(30 * sizeof(int));
int * pl;
pl = (int *)malloc(30 * sizeof(int));
int countl = 0;
while (mo[i] != po[n - 1])
{
ml[i] = mo[i];
i++;
countl++;
}
for (i = 0; i < countl; i++)
{
pl[i] = po[i];
}
if (countl == 0) { ml = NULL; pl = NULL; }
preorder(pl, ml, countl);
//右子树的中序遍历和后序遍历
int * mr;
mr = (int *)malloc(30 * sizeof(int));
int * pr;
pr = (int *)malloc(30 * sizeof(int));
int countr = n - countl - 1;
int j = countl;
for (i = 0; i < countr; i++, j++)
{
pr[i] = po[j];
}
for (i = 0, j = countl + 1; i < countr; i++, j++)
{
mr[i] = mo[j];
}
if (countr == 0) { mr = NULL; pr = NULL; }
preorder(pr, mr, countr);
}
}
}