重建二又树 | 根据先序遍历和中序遍历建立二叉树

面试题6:重建二又树

1.题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。二叉树结点的定义如下:

typedef struct BtNode
{
	struct BtNode* leftchild;
	struct BtNode* rightchild;
	ElemType data;
}BtNode,*BinaryTree;

例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},
则重建出下图所示的二叉树并输出它的头结点。

2.题目分析

在二叉树的前序遍历序列中,第一个数字总是树的根结点的值但在中序遍历序列中,根结点的值在序列的中间,左子树的结点的值位于根结点的值的左边,而右子树的结点的值位于根结点的值的右边。如下图所示,前序遍历序列的第一个数字1就是根结点的值。扫描中序遍历序列,就能确定根结点的值的位置。根据中序遍历特点,在根结点的值1前面的3个数字都是左子树结点的值,位于1后面的数字都是右子树结点的值。

由于在中序遍历序列中,有3个数字是左子树结点的值,因此左子树总共有3个左子结点。同样,在前序遍历的序列中,根结点后面的3个数字就是3个左子树结点的值,再后面的所有数字都是右子树结点的值。这样我们就在前序遍历和中序遍历两个序列中,分别找到了左右子树对应的子序列。 

既然我们已经分别找到了左、右子树的前序遍历序列和中序遍历序列,我们可以用同样的方法分别去构建左右子树。也就是说,接下来的事情可以用递归的方法去完成。

3.code

int FindIndex(const ElemType* istr, int n, ElemType x)
{
	int pos = -1;
	for (int i = 0; i < n; ++i)
	{
		if (istr[i] == x)
		{
			pos = i;
			break;
		}
	}
	return pos;
}

BtNode* CreatePI(const ElemType* pstr, const ElemType* istr, int n)//pstr代表先序
{
	BtNode* p = NULL;
	if (n > 0)
	{
		p = NewNode();
		p->data = pstr->data;
		int pos = FindIndex(istr, n, *pstr);
		if (pos == -1)		exit(1);
		p->leftchild = CreatePI(pstr + 1, istr, pos);
		p->rightchild = CreatePI(pstr + 1 + pos, istr + 1 + pos, n - pos - 1);
	}
	return p;
}

BtNode* CreateTreePI(const ElemType* pstr, const ElemType* istr, int n)
{
	if (NULL == pstr || NULL == istr || n < 1)	return NULL;
	return CreatePI(pstr, istr, n);
}
发布了88 篇原创文章 · 获赞 40 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ThinPikachu/article/details/105658821