从遍历序中重建树

根据前序遍历,我们很容易找到根(它就是前序遍历的第一个结点)。在中序遍
历中找到根的位置,就可以找到左子树和右子树各有哪些结点,分别用灰色和白色表
示。如果在前序遍历中所有灰色结点都在白色结点之前,则递归地把灰色结点和白色
结点分别建成左右子树(如箭头所示),然后加上根。如果有的白色结点在灰色结点
之前,无解(用叉表示),如图 3.6用这样的方法可以先建树,再进行后序遍历,像这
样:
bool BuildTree ( int pl , int pr , int il , int ir , int & root )
{
if ( pl > pr ) /*空树 */
{ root = 0; return true ; }
int p = index [ pl ]; /*根在原后序遍历中的位置 */
int q = p1 +p - il ; /*最后一个灰色结点在原前序遍历中的位置 */
for ( int i = pl +1; i <= q ; i ++)
if ( index [ i ] > p ) return false ; /*检查灰色是否越界 */
root = ++ nodecount ; /*给根分配结点编号 */
if (! BuildTree ( pl +1 , q , il , p -1 , left [ root ])) /*递归建立左子树 */
return false ;
if (! BuildTree ( q +1 , pr , p +1 , ir , right [ root ])) /*递归建立右子树 */
return false ;
return true ;
}
由于在任何时候,递归的参数都是原前序/后序遍历的子序列,因此只需要把前
序遍历在原序列中的起止位置(p l , p r )和后序遍历的起止位置(i l , i r )传递进去即可。由于
两个数组都是排列,可以事先预处理算出 pre[i] 在 in 中的下标 index[i] , 方便主程序编
写。
和链表类似,设置虚拟结点0作为空子树标记。仍然可以使用队列来实现空闲结
点列表,但由于在本例中没有删除操作,只需要简单设置已分配结点个数的计数器即
可。

猜你喜欢

转载自blog.csdn.net/k42946/article/details/80244699