编程之美 3.9 前序和中序得到后序

原理比较简单,首先找到前序的第一个元素,寻找在中序中间的位置,这样中序输出被分成两部分,那么这前一部分属于左子树,后面部分属于右子树,如下所示:

a b d c e f

d b a e c f

分解成为

b d

d b

c e f

e c f

然后对这两个部分采用类似的方法求解,最后得到二叉树的描述,代码如下:

/*
 * bop_3_9.cpp
 *
 *  Created on: 2012-5-25
 *      Author: ict
 */

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iostream>
using namespace std;

#define MAX 100

typedef struct NODE
{
	char ch;
	struct NODE *left;
	struct NODE *right;
}Node, *PNode;

//递归调用该方法,根据前序、中序得到后序
PNode pre_in_to_af(char *pre, char *in)
{
	int index;
	char a1[MAX];	//用于分割字符串
	char a2[MAX];
	char b1[MAX];
	char b2[MAX];

	memset(a1, 0, MAX * sizeof(char));
	memset(a2, 0, MAX * sizeof(char));
	memset(b1, 0, MAX * sizeof(char));
	memset(b2, 0, MAX * sizeof(char));

	if(strlen(pre) == 0)
		return NULL;
	if(strlen(in) == 0)
		return NULL;

	string a = pre;
	string b = in;

	PNode p = (PNode)malloc(sizeof(Node));

	index = b.find_first_of(pre[0], 0);	//找到指定字符在中序的位置

	p->ch = pre[0];
	strncpy(a1, pre + 1, index);	//复制前序的前半部分
	strncpy(a2, pre + index + 1, strlen(pre) - index -1);	//复制前序的后半部分
	strncpy(b1, in, index);			//复制中序的前半部分
	strncpy(b2, in + index + 1, strlen(in) - index -1);		//复制中序的后半部分
	p->left = pre_in_to_af(a1, b1);		//递归查找左子树
	p->right = pre_in_to_af(a2, b2);	//递归查找右子树

	return p;		//返回根节点
}

//后序遍历
void afPrint(PNode p)
{
	if(p == NULL)
		return ;

	afPrint(p->left);
	afPrint(p->right);
	printf("%c", p->ch);
	return ;
}


int main()
{
	char pre[MAX];
	char in[MAX];

	PNode head;

	scanf("%s", pre);
	scanf("%s", in);

	head = pre_in_to_af(pre, in);

	afPrint(head);

	return 0;
}


------------------------------------------------华丽的分割线---------------------------------------------------

编程之美后面的扩展问题,如果知道前序和后序遍历的结果,能重构二叉树吗?

这里我们可以做一个一般的结论:

知道两种遍历结果,如果要重构二叉树,其中一种必须是中序遍历结果。

为什么会这样呢?我们首先可以举一个非常简单的例子:

前序遍历:a b

后序遍历:b a

我们可以构造两棵二叉树满足上面的遍历结果,两棵二叉树的根节点都是a,但是一棵二叉树的b为左节点,一棵二叉树的b为右节点。

为什么会这样呢?

原来在前序遍历结果中,第一个遍历元素一定是二叉树的根节点;后续遍历结果中,最后一个元素一定是二叉树的根节点;这样的话,我们只能确定根节点,但是我们不知道中间元素哪些是左子树,哪些属于右子树,从而无法构造独一无二的二叉树。

相反,如果知道中序遍历,我们通过前序或者后序获得根节点,然后在中序中找到根节点,那么根节点左半部分为左子树,右半部分为右子树,从而可以唯一确定二叉树。

所以类似的,我们可以根据后序遍历+中序遍历,确定二叉树,代码和上面类似。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值