先来复习一下二叉树,最近在看刘汝佳写的算法艺术与信息学竞赛的学习指导
里面在讲二叉树的时候这样说道
分别用3个数组模拟指针,并对二叉树进行前序,中序和后序遍历
//对于一个节点i //有Value[i],Right[i],Left[i]3个数组 //分别表示该节点的值,左儿子节点,右儿子节点 //那么三种遍历的DFS可以这样写: void PreOrder(int root) { if(root){ Print(Value[i]); PreOrder(Left[i]); PreOrder(Right[i]); } } void InOrder(int root) { if(root){ PreOrder(Left[i]); Print(Value[i]); PreOrder(Right[i]); } } void PostOrder(int root) { if(root){ PreOrder(Left[i]); PreOrder(Right[i]); Print(Value[i]); } }
下面要实现一个已知前序和中序遍历,恢复一棵二叉树的操作
比如对于这样一棵二叉树,前序遍历依次为:ABDECF 中序遍历为:DBEAFC
/* 假定两个序列分别保存在数组Pre[i]与In[i]中 我们分别用Pl,Pr标记前序遍历的起止下标,用Il,Ir标记中序遍历的起止下标 由前序遍历的性质可以知道Pre[Pl]即为二叉树的根 于是,我们在In[i]中找到根的位置,并标记为p 由中序遍历的性质可以知道, 在In[i]中,对于i<p的节点,都在左子树中,i>p的节点都在右子树中 我们将Pre[Pl](即In[p])放入树中,并递归的建左右子树(这里用到分治的思想) 此时可以把Pre,In数组分别看成由三部分组成 对于Pre:根 + 左子树 + 右子树 Pl q Pr 对于In:左子树 + 根 + 右子树 Il p Ir 要实现递归操作,还必须知道前序遍历中,表示左子树的最后一个元素的坐标q 可以由中序遍历的坐标转换得到,q=p-Il+Pl 此时所有坐标都已经出现,源代码如下 */ void BuildTree(int Pl,int Pr,int Il,int Ir,int Root) { if(Pl>Pr){ Root=0; return; } int p,q; p=Find(Pre[Pl]); q=Pl+p-Il; Root=++NodeCount; //NodeCount为节点序号 BuildTree(Pl+1,q,Il,p-1,Left[Root]); BuildTree(q+1,Pr,p+1,Ir,Right[Root]); }