一、概述
给出一棵二叉树的中序和层序遍历,输出前序和后序遍历。并分别输出其从右往左看,从右上往左下看,从上往下看能够看到的节点数量。注意节点可以互相覆盖,边之间的角度都是九十度。
二、分析
核心就在于重建树。我们之前重建树都是不涉及层序的,因为只要涉及层序遍历,重建树的画风就不一样了。
先看原来的,以前序中序重建二叉树为例。我们这样做:
根据前序找到根,在中序定位根;
在中序找到左右子树的元素,则在前序也可以找到对应的元素;
最重要的一点:无论在前序还是中序,只要是属于同一棵子树的元素,就一定扎堆在一起。
因此我们可以设计出递归程序。
但是有层序就不一样了。在层序遍历中,左子树和右子树的元素是乱七八糟混在一起的,我们不能直接通过两个端点把它们定位出来。为了以同样的手段重建树,我们采用以下方法:
对于中序遍历,处理方法一样;
层序遍历使用vector保存;
每次调用重建树函数,都要将层序遍历中的属于左子树和右子树的部分分开来,并保证它们的相对顺序不变;
这样就退化成和之前一样的情况了。
怎么分开呢?代码如下:
for(it=level.begin();it!=level.end();it++)
{
int left=0;
for(int j=il;j<rootin;j++)
{
if(in[j]==*it)
{
l.push_back(*it);
//cout<<"左边有"<<*it<<"\n";
left=1;
break;
}
}
if(left==0)
{
for(int j=rootin+1;j<=ir;j++)
{
if(in[j]==*it)
{
r.push_back(*it);
//cout<<"右边有"<<*it<<"\n";
break;
}
}
}
}
实质是两个循环,第一个循环遍历所有层序的节点,对于层序中的每个节点,遍历中序,如果发现它在中序中的位置是在根节点左边,那么它属于左子树,否则属于右子树。
之后我们可以得到两个vector,分别保存左子树和右子树的元素的层序遍历。
接下来就可以开始递归了。
代码如下:
Node* create(vector<int> level,int il,int ir)
{
if(il>ir||level.size()==0)
return NULL;
Node* root=new Node;
roo