知识点:
1.由前序遍历+中序遍历||后序遍历+中序遍历可以得到一个完整的二叉树,由前序+后序遍历无法确定一个二叉树。
2.前序和后序遍历可以确定根(前序遍历第一个为根,后序遍历最后一个为根),此性质与遍历顺序有关,因为前序遍历是“根左右”,后序遍历是“左右根”。
3.中序遍历的特征:如果已知根节点,那么在中序遍历的结果中,排在根结点左边的点都在左子树上,排在根节点右边的都在右子树上。
已知上述条件,可以通过中序和前序遍历结果得到整颗二叉树,可以通过递归的方法。思路为把每颗子树的子根看着一个根节点,先左后右得递归,递归边界为没有左儿子时。
给出代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node //定义节点,用typedef较为方便
{
int data;
struct Node *l,*r;
}node;
node *creat(int n,char *qian,char *zhong)//建立二叉树
{
int i;
node *root;//定义根节点
if(n==0)//递归边界
{
return NULL;
}
root=(node*)malloc(sizeof(node));//给根结点开空间
root->data=qian[0];//将前序遍历结果的最前面的值赋给根节点(因为前序遍历结果的首个一定为树的根)
for(i=0;i<n;i++)//在中序遍历中找到根节点所在的位置,即<i的部分为左子树,>i的部分为右子树
{
if(qian[0]==zhong[i]) break;
}
//接下来是分别递归左右子树,遵循先左后由的原则
root->l=creat(i,qian+1,zhong);//由于前序遍历的第一个已经放入树中了,所以+1更新前序数组,且只在中序遍历结果中查找<i部分的值,递归思想,我也不太讲的清,推荐自己模拟感受一下
root->r=creat(n-1-i,qian+1+i,zhong+1+i);//右子树递归
return root;
}
int imax(int a,int b)//自定义比大小函数
{
if(a>=b) return a;
else return b;
}
int deep(node *root)//计算二叉树深度,也用递归
{
int hl,hr,max;
if(root!=NULL)
{
//分别递归左右子树的深度
hl=deep(root->l);
hr=deep(root->r);
max=imax(hl,hr);//比较左右子树的大小,取较大的
return max+1;//返回上层递归,所以层数+1,这里要思考一下,计算深度是从下往上的,而不是从上往下,从递归边界也可以看出。
}
else//递归边界
{
return 0;
}
}
int main()
{
char qian[51],zhong[51],n,h;
while(~scanf("%d",&n))
{
scanf("%s %s",qian,zhong);
node *root;
root=creat(n,qian,zhong);
h=deep(root);
printf("%d\n",h);
}
return 0;
}