2024王道408数据结构 P144 T15
思考过程
- 题目的要求是给定我们一串先序序列pre,让我们把这棵二叉树的后序序列post求出来。
- 那么首先我们要清楚先序序列和后序序列之间的关系。在先序序列中顺序是根左右,后序序列中顺序是左右根,干讲可能有点枯燥,我们举个例子,假设二叉树长这样
显然这棵树的先序序列中第一个是这棵树的根结点,而在后序序列中根结点在最后一个位置。我们其实是把这样一个序列分成两半来看的
像图上那样,也就是分为左子树和右子树两个部分来看。
- 而先序序列中的B呢也就是左子树的根结点在后序序列中是在左子树的最后一个位置,然后我们接着砍一半
此时的结点D在先序序列中是最后一个,在后序序列中则是第一个,明白这一点我们代码就很好写了。
代码过程
- 首先我们需要一个变量half用来放左子树和右子树的临界点,把先序序列和后序序列的最前面和最后面都标上名称方便我们访问
在函数的参数当中我们也这么去写
void PreToPost(char pre[], int l1, int h1,char post[],int l2,int h2)
l1和h1分别用来表示先序序列的起点和终点,l2和h2用来表示后序序列的起点和终点。 - 首先我们在函数中先替换第一个也就是A结点的位置,
post[h2]=pre[l1];
这样就是把先序序列的第一个元素放在后序序列的最后一个位置上,然后把half给赋值(h1-l1)/2
就表示把左右子树给分开了。 - 然后利用递归
PreToPost();
这里面的参数可有讲究了,在我们替换第一个元素A时是从l1开始的,那么在这里我们就要让先序序列pre从l1+1开始,一直到l1+half结束也就是BDE这一部分,此时half是为3的。在后序序列post中,是从l2开始,从l2+half-1结束的也就是DEB这一部分所以遍历左子树的递归函数参数应该是
PreToPost(pre, l1 + 1, l1 + half, post, l2, l2 + half - 1);
- 那么遍历右子树的递归函数参数也一样了,先序序列pre是从C开始的,也就是l1+half+1,一直到h1结束,后序序列post是从l2+half开始,到h2-1结束,也就是这样
程序应该写成
PreToPost(pre, l1 + half + 1, h1, post,l2 + half, h2 - 1);
这样就写完了。
完整代码
//
// Created by 黎圣 on 2023/8/22.
//
/*
* 设有一棵满二叉树(所有结点值均不同),已知其先序序列为pre,设计一个算法求其后序序列post.
*/
#include "iostream"
using namespace std;
void PreToPost(char pre[], int l1, int h1, char post[], int l2, int h2)
{
int half;
if (l1 <= h1)
{
post[h2] = pre[l1];
half = (h1 - l1) / 2;
PreToPost(pre, l1 + 1, l1 + half, post, l2, l2 + half - 1);
PreToPost(pre, l1 + half + 1, h1, post,l2 + half, h2 - 1);
}
}
int main()
{
char pre[8] = "ABDECFG";
char post[8];
PreToPost(pre, 0, 6, post, 0, 6);
for (int i = 0; i < 7; i++)
printf("%c ", post[i]);
return 0;
}
最后感谢b站up主@吸血小金鱼