题目描述:
一般来说,给定二叉树的先序遍历序列和后序遍历序列,并不能唯一确定该二叉树。
比如图一中的两棵二叉树,虽然它们是不同二叉树,但是它们的先序、后序遍历序列都是相同的。但是对于“真二叉树”(每个内部节点都有两个孩子的二叉树),给定它的先序、后序遍历序列足以完全确定它的结构。
将二叉树的n个节点用[1, n]内的整数进行编号,输入一棵真二叉树的先序、后序遍历序列,请输出它的中序遍历序列。
输入格式:
第一行为一个整数n,即二叉树中节点的个数。
第二、三行为已知的先序、后序遍历序列。
要求:
1 ≤ n ≤ 4,000,000
输入的序列是{1,2…n}的排列,且对应于一棵合法的真二叉树
输出格式:
仅一行,给定真二叉树的中序遍历序列。
输入样例:
5
1 2 4 5 3
4 5 2 3 1
输出样例:
4 2 5 1 3
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
题解:
//本题的逻辑结构:二叉树
//本题的存储结构:链式
//解题思路和算法:按照先序遍历先输出根节点再遍历和后序遍历先遍历再输出根节点的特征,分析两个遍历序列的特点找出规律解决问题
// 用递归的方法通过参数(树的先序和后序的前后端)去确定哪些节点是左子树,哪些是右子树,然后递归继续构造
//效率:时间复杂度O(n)、空间复杂度O(n):
//测试数据: (1)输入:5
// 1 2 4 5 3
// 4 5 2 3 1
// 输出:4 2 5 1 3
// (2)输入:13
// 1 2 4 8 9 5 3 6 7 10 12 13 11
// 8 9 4 5 2 6 12 13 10 11 7 3 1
// 输出:8 4 9 2 5 1 6 3 12 10 13 7 11
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef int ElementType;
ElementType preOrder[1000];
ElementType AftOrder[1000];
int n;
typedef struct TNode * Position;
typedef Position BinTree;
struct TNode
{
BinTree Left;
BinTree Right;
ElementType content;
};
BinTree buildNode(int leftPos, int leftLen, int rightPos, int rightLen)
{
int left;
int findRoot;
Position Root = (BinTree)malloc(sizeof(struct TNode));
Root->content = preOrder[leftPos];
Root->Right = Root->Left = NULL;
if (rightPos == rightLen)
return Root;
for (int i = rightPos; i <= rightLen; i++)
{
if (AftOrder[i]==preOrder[leftPos + 1])
{
findRoot = i;
break;
}
}
left = findRoot-rightPos+1;//下一个节点左边的数值
Root->Left = buildNode(leftPos+1, leftPos+left, rightPos, findRoot);
//参数说明:树的先序和后序的前后端,
// 通过这四个值去确定哪些节点是左子树,哪些是右子树,然后递归继续构造
Root->Right = buildNode(leftPos+left+1, leftLen, findRoot+1, rightLen-1);
return Root;
}
void middleIterate(BinTree Root)
{
if (Root==NULL)
return;
middleIterate(Root->Left);
printf("%d ", Root->content);
middleIterate(Root->Right);
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &preOrder[i]);
for (int j = 0; j < n; j++)
scanf("%d", &AftOrder[j]);
BinTree Root = buildNode(0, n-1, 0, n-1);
middleIterate(Root);
return 0;
}