已知前序与中序、后序与中序建树是常遇到的算法问题。若已知前序序列与后序序列,要求输出满足条件的树的个数或者输出所有可能的树的中序序列,该怎么解决?下面我们一步步讨论这个问题。
首先,已知一个树的结点数n,共有多少种树形?(或者,已知一颗树的先序/中序/后序序列,共有多少种树形?)
答案是 C m n / ( n + 1 ) C_{m}^{n}/(n+1) Cmn/(n+1)种。点这里了解一下卡特兰数
那么,这里就有一种暴力解法,就是建立所有可能的树形,将先序序列填入某一树形,比较此树的后序序列是否与给定后序序列相同,若相同则找到一个解,若不相同,则填入下一个树形,直到填完所有可能树形。当树的结点为10时,那么总共有16796种树形,因此这种暴力解法时间复杂度相当高。
那么我们换一种思考方式,我们先来看看先序与后序序列的排布规律。以下面这棵树来举例:
其先序序列为: 1 2 3 4 6 7 5
后序序列为:2 6 7 4 5 3 1
首先我们要知道:
先序序列遍历顺序是:根结点-左子树-右子树
后序序列遍历顺序是:左子树-右子树-根结点
很明显,我们可以看出结点在先、后序列中的排布有以下这些特征:
【1】、在先序序列中,根结点在子树中的结点前面,在后序序列中,根结点在子树中的结点后面。
【2】、以任一节点为根结点时,其子树在后序序列中排布都是先左子树后右子树,而根结点排在最后。
那么,反过来思考,已知这个先序与后序序列所确定的树是唯一的吗?进一步推广:怎么通过先序与后序序列判断是否存在唯一的树呢?
现在,我们来一步步分析已知先序与后序的建树过程:
①、根据特征【1】可知:根结点为先序序列第一个节点以及后序序列最后一个结点,因此根结点为1。
②、先序序列中第二个结点为2,其在后序序列中的位置是第一个,那么根据特征【2】我们可以知道结点2是没有子树的,而且结点2要么在根结点的左子树,要么在右子树。假设结点2在右子树,那么由特征【2】可知根结点1没有左子树,而且先序序列中结点2后面的结点全部为结点2的子树上的结点。再看后序序列,由特征【2】可知,结点2后面的结点不可能是其子树上的结点。因此,假设显然与已知矛盾。这样,我们又知道结点2是结点1的左孩子,且结点2没有子结点。
③、先序序列第三个位置上的结点为3,该结点在后序