C,核心代码有详细注释,自写,请读者视情参考
思想:
根据中序排序的特点我们可以知道,如果我们选中其中某一节点,它的左边一定是这个节点的左子树,右边一定是这个节点的右子树。
根据先序排序的特点我们可以知道,如果我们选中其中某一节点,它右边的节点一定是先排列完左子树,再排列右子树。
那么我们能否根据这两个规律,确定唯一的二叉树?
如果确定能够构造唯一的二叉树,那么根据后序遍历的算法很容易得出后序序列。
所需知识:
C,二叉树,先序遍历,中序遍历,后序遍历
途径:
采用分治思想,先分后合。将左子树和右子树逐层分开,直到左边没有节点,右边没有节点,此时该节点为叶子节点,再进行合并,接上上一层的节点。分治法一般采用递归实现拆分和合并,所以这里用一个递归函数来实现。
举例:
(建议直接看代码,不清楚再看这里)
对于示例先序pre[] = abcde,中序in[] = bcade,从先序第一个节点a开始,在中序中找到a,则a的左子树为preL[] = bc(这里可以看出左子树是两个节点),右子树为preR[] = de(两个)。
那么,我们可以知道先序中a的后面两个节点是左子树inL[] = bc,再后面两个是右子树inR[] = de。把左子树接上a,右子树接上a(因为是递归,所以会从底层一个一个接上的)。
对左子树再进行拆分,先序preL[] = bc,中序inL[] = bc,从先序第一个节点b开始,在中序中找到b,则b的左子树为 (这里可以看出该节点没有左子树),右子树为c(一个)。
那么,我们可以知道先序中b的后面零个节点是左子树,再后面一个是右子树。再对右子树进行拆分,发现右子树只有一个,已经是叶子了,那么接上上一层。
右子树同样道理,拆分到底层叶子不可再拆分,再从底层一层一层接上去。
.
当然,若是对后序比较熟悉的话,就会发现,这接上去的顺序其实就是后序的顺序,针对这道题目可以直接输出。
所以这道题有更简单的写法,简单写法代码贴在最后以供参考,但这道题目的是理解三种序列的特点,熟练的读者可以尝试自行修改。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(disable:4996)
#define ElemType char
#define OK 1
#define ERROR 0
#define MaxNodeCount 50
typedef int Status;
typedef struct BiTreeNode
{
ElemType data;
struct BiTreeNode *lchild;
struct BiTreeNode *rchild;
}BiTreeNode, *Bitree;
Bitree Stack[MaxNodeCount];//栈
int base = 0, top = 0;
char pre[100];//先序
char in[100];//后序
//根据给出前序和中序序列,创建二叉树。
//preL:前序左界,preR前序右界,inL中序左界,inR中序右界
//返回:当前构造子树根节点
Bitree PreInCreat(int preL, int preR, int inL, int inR) {
Bitree root;
root = (BiTreeNode *)malloc(