OJ题目 P1138 American Heritage 根据二叉树的前序遍历和中序遍历求出二叉树的后序遍历

题目描述

给出一棵二叉树的前序遍历 (preorder) 和中序遍历 (inorder),求它的后序遍历 (postorder)。该二叉树的结点的值为大写的26个字母的其中一个,且各个结点的值不重复。

OJ题目 P1138 American Heritage 根据二叉树的前序遍历和中序遍历求出二叉树的后序遍历_第1张图片

相关知识

前序遍历:先遍历根结点,再遍历左子树和右子树,对左子树和右子树的遍历也遵循根左右的原则

中序遍历:先遍历左子树,再遍历根结点,最后遍历右子树,对于左右子树的遍历也遵循左根右的原则

后序遍历:先遍历左子树,再遍历右子树,最后遍历根结点,对于左右子树的遍历也遵循左右根原则 

如何根据二叉树的先序遍历和中序遍历还原该二叉树的形态

  1. 在先序遍历中找到第一个结点,该节点为该二叉树的根结点
  2. 在中序遍历中找到根结点的位置,则在根结点的左边为左子树的节点元素,在根结点的右边为右子树的元素,继续对左子树和右子树用一样的方法找到左子树和右子树的左子树和右子树。

从上诉方法我们可以很明显的看到求解此题的方法是递归的,所以需要用到递归的算法

解题思路

对于后序遍历而言,我们要先遍历左子树,再遍历右子树,最后遍历根结点,所以递归算法思想是:

  1. 找到该树的左子树
  2. 找到该树的右子树
  3. 输出根结点的值 

对该树的左子树和右子树继续调用本方法,直到该树的左子树和右子树均为空 时即到达叶子节点时,输出该节点的元素的值即可得到后序遍历的结果

程序源代码以及运行结果如下,再题目的源代码中给出了完整的注释,即思考过程

程序源代码:

//给定二叉树的前序遍历和中序遍历求出树的后序遍历,

#define _CRT_SECURE_NO_WARNINGS
#include
#include		          //该头文件包含了malloc函数的声明;
#include
#define N 26            //二叉树的节点个数不确定,确定的是,每一个结点元素的值都是大写的26个英文字母中的其中一个,且不会有重复,所以显然该二叉树的结点不会超过26个

//给定二叉树的先序遍历和中序遍历,求其后序遍历结果,需要用到递归的思想,其求解步骤有很明显的递归思想


//设计一个函数,该函数的功能是找到一个字符数组中数组元素值为c的元素的数组下标,并作为函数值来返回;
int find_index(char *p,char c)
{
	for (int i = 0;p[i] != '\0'; i++)
	{
		if (p[i] == c)
			return i;
	}
}


void Solve_Result_Post_Order(char *pre, char *middle)             
{
	char ltree_pre[N],rtree_pre[N],ltree_middle[N],rtree_middle[N];            //分别找到左子树,和右子树以及他们的前序遍历和后序遍历

	if (strlen(pre)==0 || strlen(middle)==0)                   //若子树为空则返回
	{
		return;
	}
	
	
	
	
	int flag = find_index(middle,pre[0]),count,lmark=1,rmark=0;           //找到中序遍历中根结点的位置,lmark用于辅助寻找左子树的先序遍历
	count = flag + 1;
	
	
	
	
	//分别找到左子树和右子树的中序遍历



	
	
	//找到左子树的中序遍历
	for (int i = 0; i < flag; i++)
	{
		ltree_middle[i] = middle[i];
	}
	ltree_middle[flag] = '\0';             //注意为其添加字符串结束标识符
	
	
	
	
	//找到左子树的前序遍历

	for (int i = 0; i < flag; i++)
	{
		ltree_pre[i] = pre[lmark];
		lmark++;
	}
	ltree_pre[lmark] = '\0';

	
	
	//找右子树的中序遍历
	for (int i = count; middle[i] != '\0'; i++)
	{
		rtree_middle[rmark] = middle[i];
		rmark++;
	}
	rtree_middle[rmark] = '\0';
	
	
	
	//找到右子树的先序遍历
	int assist = 0;
	for (int i = count; pre[i] != '\0'; i++)
	{
		rtree_pre[assist] = pre[i];
		assist++;
	}
	rtree_pre[assist] = '\0';

	
	
	
	//先对左子树进行递归调用本函数,再对右子树递归调用本函数,最后打印本结点的值

	Solve_Result_Post_Order(ltree_pre, ltree_middle);
	Solve_Result_Post_Order(rtree_pre, rtree_middle);
	printf("%c", pre[0]);

				
}




int main()
{

	char PreOrder[N];
	char MiddleOrder[N];
	while (scanf("%s",MiddleOrder) != EOF)
	{
		scanf("%s",PreOrder);
		Solve_Result_Post_Order(PreOrder, MiddleOrder);
		printf("\n");
	}
	return 0;
}

运行结果截图

OJ题目 P1138 American Heritage 根据二叉树的前序遍历和中序遍历求出二叉树的后序遍历_第2张图片

你可能感兴趣的:(OJ题目,数据结构,算法,c语言,程序人生)