计算机机试题:二叉树遍历

二叉树是数据结构中十分重要的一种树。通常我们定义是:

struct Node 
{
	Node * lchild;
	Node * rchild;
	char c;
}Tree[50];

还有就是二叉树的前序遍历,中序遍历和后序遍历也是十分重要。接下来看一个例题:

题目描述:
二叉树的前序、中序、后序遍历的定义:
前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树;
中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树;
后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。
给定一棵二叉树的前序遍历和中序遍历,求其后序遍历(提示:给定前序遍历与中序遍历能够唯一确定后序遍历)。
输入:
两个字符串,其长度n均小于等于26。
第一行为前序遍历,第二行为中序遍历。
二叉树中的结点名称以大写字母表示:A,B,C....最多26个结点。
输出:
输入样例可能有多组,对于每组测试样例,
输出一行,为后序遍历的字符串。
样例

输入:
ABC
BAC
FDXEAG
XDEFAG
样例输出:
BCA
XEDGAF
来源:
2006年清华大学计算机研究生机试真题

代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Node 
{
	Node * lchild;
	Node * rchild;
	char c;
}Tree[50];
int loc ;       //静态数组中已经分配的节点个数
Node * creat()
{
	Tree[loc].lchild = Tree[loc].rchild = NULL;
	return &Tree[loc++];
}
char str1[30], str2[30];  //保存前序和中序遍历字符串

//后序遍历
void postOrder(Node * T)
{
	if(T->lchild != NULL)
	{
		postOrder(T->lchild);
	}
	if(T->rchild != NULL)
	{
		postOrder(T->rchild);
	}
	printf("%c ",T->c);
}
//由字符串的前序遍历和中序遍历还原树,并返回其根节点。
Node * build(int s1, int e1, int s2, int e2)
{
	Node * ret = creat();
	ret->c = str1[s1];
	int rootIdx;
	for(int i=s2; i<=e2; i++)
	{
		if(str2[i] == str1[s1])
		{
			rootIdx = i;
			break;
		}
	}
	if(rootIdx != s2)      //若左子树不为空
	{
		ret->lchild = build(s1+1, s1+(rootIdx-s2), s2, rootIdx-1);
	}
	if(rootIdx != e2)
	{
		ret->rchild = build(s1+(rootIdx-s2)+1, e1, rootIdx+1, e2);
	}
	return ret;
}



int main()
{
	while(scanf_s("%s", str1, 10)!=EOF)
	{
		scanf_s("%s",str2,10);
		loc = 0;
		int L1 = strlen(str1);
		int L2 = strlen(str2);
		Node * T = build(0, L1-1, 0, L2-1);
		postOrder(T);
		printf("\n");
	}
	return 0;
}


这个代码是书上的代码,其中最核心也最难搞懂的就是build函数。其实最核心的在于这四个参数,其中s1和e1代表的是每次前序遍历的起点和终点,s2和e2代表的是每次中序遍历的起点和终点。就是每次遍历都有一个范围,想想根据前序遍历和中序遍历求后序遍历的算法,其实每次我们都会根据当前的根节点将树划分为左右子树。

猜你喜欢

转载自blog.csdn.net/xckkcxxck/article/details/80981472
今日推荐