PTA(树和二叉树)1-9 确定二叉树(先序序列+中序序列)
PTA(树和二叉树)1-9 确定二叉树(先序序列+中序序列)
zhangzhang1-9 确定二叉树(先序序列+中序序列)
分数 3
作者 黄龙军
单位 绍兴文理学院
要求实现函数,根据二叉树的先序序列和中序序列确定二叉树并返回指向二叉树根结点的指针。二叉树采用二叉链表存储,结点结构如下:
1 | struct BiTNode { // 结点结构 |
函数接口定义:
1 | BiTNode* CreateBT(int* pre, int *in, int n); |
其中参数 pre是指向先序序列数组首元素的指针, in是指向中序序列数组首元素的指针 ,n是结点总数。
裁判测试程序样例:
1 |
|
输入样例:
1 | 9 |
输出样例:
1 | 7 4 2 8 9 5 6 3 1 |
- 我天,这题也好妙,先一直以为只能用脑子想出来
- 现在可以通过代码实现了
答案
可以根据先序序列和中序序列的特点,使用递归的方法来构建二叉树。先序序列的第一个元素就是根节点,然后在中序序列中找到根节点的位置,根节点左边的元素就是左子树的中序序列,右边的元素就是右子树的中序序列。根据中序序列中左子树和右子树的节点个数,在先序序列中也可以划分出左子树和右子树的先序序列,然后递归地构建左子树和右子树。
1 | BiTNode* CreateBT(int* pre, int *in, int n) { |
为什么创建右子树的第一个参数是pre + rootIndex + 1
核心背景:遍历序列的特性
二叉树的先序遍历(
pre)顺序是:根节点 → 左子树 → 右子树二叉树的中序遍历(
in)顺序是:左子树 → 根节点 → 右子树具体分析
假设当前递归处理的序列长度为
n,即当前子树包含n个节点。根节点的确定:
先序序列的第一个元素
pre[0]是当前子树的根节点。中序序列中根节点的位置:
在中序序列
in中找到根节点的索引rootIndex,则:- 中序序列中,
[0, rootIndex-1]是左子树的节点(共rootIndex个节点)。 - 中序序列中,
[rootIndex+1, n-1]是右子树的节点(共n - rootIndex - 1个节点)。
- 中序序列中,
先序序列中右子树的起始位置:
先序序列的结构是
[根节点][左子树的所有节点][右子树的所有节点]。- 根节点占用
pre[0]位置。 - 左子树有
rootIndex个节点,因此左子树在预序序列中占据pre[1]到pre[rootIndex](共rootIndex个元素)。 - 因此,右子树的第一个节点在预序序列中的位置是
rootIndex + 1(跳过根节点和左子树的所有节点)。
- 根节点占用
1. 核心依据(序列特性)
- 先序序列:根节点 → 左子树先序 → 右子树先序(第一个元素必为当前树的根)。
- 中序序列:左子树中序 → 根节点 → 右子树中序(根节点可分割左右子树)。
2. 步骤拆解
- 终止条件:若节点数
n=0(空树 / 子树),返回NULL。 - 创建根节点:取先序序列第一个元素
pre[0]作为当前树的根。 - 定位根节点在中序的位置:遍历中序序列,找到与根节点值相等的索引
rootIndex。 - 递归构建左子树:
- 左子树先序序列:从
pre[1]开始,长度为rootIndex(左子树节点数 = 根节点在中序的索引)。 - 左子树中序序列:从
in[0]开始,长度为rootIndex。
- 左子树先序序列:从
- 递归构建右子树:
- 右子树先序序列:从
pre[rootIndex+1]开始,长度为n-rootIndex-1(总节点数 - 左子树节点数 - 根节点)。 - 右子树中序序列:从
in[rootIndex+1]开始,长度为n-rootIndex-1。
- 右子树先序序列:从
- 返回根节点:当前树构建完成,返回根节点指针,供上层递归使用。


