已知一棵二叉树的先序序列跟中序序列,构造一棵二叉树

一棵二叉树如果给定其中序序列及其前序,后序,层次遍历中的任何一种就可以唯一确定一颗二叉树。然而先序序列与后序序列无法确定一棵二叉树。

我们以二叉树的先序及中序序列为例,看一下怎样构造一棵二叉树。

假设二叉树的先序及后序序列分别为ABCDEF及CBAEDF:

我们知道,二叉树的先序序列是先遍历根结点,而后遍历左右子树。即二叉树的先序序列第一个结点就是其根结点。而中序则是先遍历左子树,再根结点,最后右子树。即根结点在中序序列的中间,将其分为两段,左边为左子树的中序序列,右边为右子树的中序序列。在上例中,由先序序列确定以A为根结点,由中序序列确定CB为其左子树,EDF为其右子树;

已知一棵二叉树的先序序列跟中序序列,构造一棵二叉树_第1张图片

这样我们确定了左子树,根结点与右子树。接下来的事情就简单了,用上述方法继续确定左子树跟右子树的形状。即左子树的先序序列为BC,中序序列为CB。右子树的先序序列为DEF,中序序列为EDF。

用同样的方法,我们可以确定A的左子树的根结点为B,C为B的左子树。A的右子树的根结点为D,E为D的左子树,F为D的右子树。即最终可以确定二叉树的形状为:

已知一棵二叉树的先序序列跟中序序列,构造一棵二叉树_第2张图片

代码的话则明显是一个递归的过程:

①首先取先序序列第一个元素,然后再遍历中序序列找到该元素,将中序序列分为两段。即分为左子树和右子树。

②递归地构造左子树与右子树,然后将其与根结点链接。最后形成二叉树。

假设先序序列与中序序列分别保存在int型数组pre[l1,……,r1]和in[l2,……,r2]中。则构造二叉树的代码如下:

BTNode* CreateBT(int pre[], int l1, int r1, int in[], int l2, int r2){
    BTNode *s;
    int i;
    if(r1 < l1)                        //l1>r1代表数组的长度为0,即作为递归的出口,表示该子树已
        return NULL;                   //经构造完成
    s = (BTNode*)malloc(sizeof(BTNode*));
    s->rchild = s->lchild = NULL;
    for(i=l2; idata = in[i];
    s->lchild = CreateBT(pre, l1+1, l1+i-l2, in, l2, i-1);  //递归构造左子树
    s->rchild = CreateBT(pre, l1+i-l2+1, r1, in, i+1, r2);  //递归构造右子树
    return s;
}

最后再来分析一下递归调用时候的参数问题。我们在遍历中序序列的时候,确定了根结点的位置在i。即左子树的个数为i-l2个。而右子树的个数为r2-i个。也就是中序序列从下标l2开始到i-1开始为其左子树,下标i+1开始到r2为其右子树(i为根结点,已经参与构造,所以不用传递)。同样,先序序列中除开第一个元素l1,之后i-l2个元素为其左子树。左子树之后r2-i个元素为其右子树。故有了上面递归时候的参数。

你可能感兴趣的:(已知一棵二叉树的先序序列跟中序序列,构造一棵二叉树)