欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

通过中序和先序/后序序列创建二叉树

程序员文章站 2022-05-06 21:34:54
...

在二叉树的相关题目中,我们经常会碰到这样的问题,给出一颗二叉树的前序遍历和中序遍历,或者是给出它的后序遍历和中序遍历,让我们画出这个二叉树或者是用代码实现如何用上面两种情况来创建这个二叉树。

首先我们来看看给出先序遍历序列和中序遍历序列如何画出这颗二叉树:
通过中序和先序/后序序列创建二叉树
首先,先序遍历序列中的第一个字母肯定是这颗二叉树的根节点,然后在中序遍历的序列中找到这个根节点,以这个根节点作为分割,在中序遍历序列中找到二叉树根节点的左右子树。
如下图所示:

通过中序和先序/后序序列创建二叉树
接着我们将左子树的先序遍历序列和中序遍历序列单独拿出来研究,跟上一步一样,线序遍历序列中第一个字母为左子树的根节点,然后在中序遍历序列中找到根节点并以它作为分割找到此时的根节点的左右子树。如下图所示;

通过中序和先序/后序序列创建二叉树
同样的再将B节点的右子树单独拿出来分析我们就可以很容易得到以B为根节点的二叉树如下:

通过中序和先序/后序序列创建二叉树
然后再分析A节点的右子树,它的右子树只有G和H两个节点,根据先序遍历和中序遍历的规则可以容易推出G为根节点,H为G的右子树,G的左子树为空,所以得到最终的二叉树:

通过中序和先序/后序序列创建二叉树
上面是由先序遍历序列和中序遍历序列推出二叉树的过程,由后序遍历序列和中序遍历序列同样的过程也可以画出一颗二叉树,但我们需要知道的是,如果只给出了先序遍历序列和后序遍历序列,我们无法画出一颗确定的二叉树,因为先序遍历和后序遍历的根节点是在最前面和最后面,因此我们无法推断出这个根节点的左右子树到底有哪些。所以说如果没有给出中序遍历序列,我们将无法得到一颗二叉树。

接下来我们用代码实现用先序遍历序列和后序遍历序列创建一颗二叉树。

//找到中序序列中的根节点
int FindIs(char* Is, int n, char val)
{
	int pos = -1;
	for (int i = 0; i < n; i++)
	{
		if (Is[i] == val)
		{
			pos = i;
			break;
		}
	}
	return pos;
}

BtNode* CreatePI(char* ps, char* Is, int n)
{
	BtNode* s = NULL;
	if (n > 0)
	{
		s = Buynode();
		s->data = ps[0];
		int pos = FindIs(Is, n, ps[0]);//找到中序序列中根节点的位置
		if (pos == -1)exit(EXIT_FAILURE);//没有找到就结束程序
		s->leftchild = CreatePI(ps + 1, Is, pos);
		s->rightchild = CreatePI(ps + 1 + pos, Is + 1 + pos, n - pos - 1);
	}
	return s;
}
BtNode* CreateTreePI(char* ps, char* Is, int n)
{
	BtNode* s = NULL;
	if (ps != NULL && Is != NULL && n > 0)
	{
		s = CreatePI(ps, Is, n);
	}
	return s;
}

我们给出需要进行测试的主函数代码如下:

int main()
{
	BinaryTree root = NULL;
	char pstr[] = "ABCDEFGH";//先序序列
	char Istr[] = "CBEDFAGH";//中序序列
	int psn = strlen(pstr);
	int Isn = strlen(Istr);
	if (psn == Isn)//中序序列和先序序列的长度必须相等
	{
		root = CreateTreePI(pstr,Istr,Isn);
	}
	PreOrder(root);
	cout << endl;
	InOrder(root);
	cout << endl;
	EndOrder(root);
	cout << endl;
	return 0;
}

通过运行结果我们可以看到这颗二叉树通过给出的先序序列和中序序列被创建出来了:

通过中序和先序/后序序列创建二叉树