【九度oj】1385 重建二叉树

来源:互联网 发布:ricequant 知乎 编辑:程序博客网 时间:2024/05/22 02:28

原题地址:http://ac.jobdu.com/problem.php?pid=1385

题目描述:

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 {1,2,4,7,3,5,6,8} 和中序遍历序列 {4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。


算法描述:

前序遍历:根左右;中序遍历:左根右;后序遍历:左右根。

前序遍历序列 {1,2,4,7,3,5,6,8} 中,前序序列中的第一个元素:1作为根将中序遍历序列 {4,7,2,1,5,3,8,6} 分为两部分,这两部分分别对应前序遍历序列中的两部分。

即:子前序遍历序列 {2, 4, 7} 和子中序遍历序列 {4, 7, 2} 。然后迭代使用前序序列中的第一个元素作为分隔符将中序遍历序列隔成两个序列。

分成三个函数:主函数、midFind(找到前序序列第一个对应在中序序列的分隔位置)、post(主迭代函数)。

post 中如果出现的 left 和 right 分别代表子树的范围(前序、中序的子树范围大小关系是一致的),如果:

(1)left > right,则此子树为空;(2)left == right,则此子树仅有一个根节点;(3)left < right,继续迭代。

注意:

这题最坑爹的地方,如果是(1)为空子树则不用判断;如果是(3)迭代时需要用 midFind 寻找判断是否元素存在;但是如果是(2)仅有一个根节点时,我忘记比较前序的根节点与后序的根节点是否是同一元素,不是一个元素则说明前序、中序不是同一个二叉树。

同时,再次迭代的顺序一定不能错,要记录后序序列,所以 post 按照 left - right - root 顺序引用。

#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX 1005using namespace std;int preArray[MAX];int midArray[MAX];int postArray[MAX];int postIndex;int midFind(int *array, int left, int right, int target){    for(int i=left; i <= right; i++)    {        if(array[i] == target)            return (i - left);    }    return MAX;                       // return MAX; means "end" }    int post(int preLeft, int preRight, int midLeft, int midRight){    //  1. empty subtree      if(preLeft > preRight || midLeft > midRight)        return 1;        //  2. subtree is just a root node      if(preLeft == preRight || midLeft == midRight){        if (preArray[preLeft] != midArray[midLeft])            return 0;        else{            postArray[postIndex] = preArray[preLeft];            postIndex ++;            return 1;        }    }         //  3. normal subtree       int midOffset = midFind(midArray, midLeft, midRight, preArray[preLeft]);    if(midOffset == MAX)              // can't find the target     {        return 0;    }    else    {        // 此处 if 顺序一定不能错,要记录后序所以 post 按照 left - right - root 顺序         if( post(preLeft + 1, preLeft+midOffset, midLeft, midLeft+midOffset - 1) &&             post(preLeft+midOffset + 1, preRight, midLeft+midOffset + 1, midRight))        {            postArray[postIndex] = preArray[preLeft];            postIndex ++;            return 1;        }        else            return 0;    }}int main(){    int n;    while(scanf("%d", &n)==1)    {        memset(preArray, 0, MAX);        memset(midArray, 0, MAX);        memset(postArray, 0, MAX);        postIndex = 0;                for(int i=0; i<n; i++)            scanf("%d", &preArray[i]);                    for(int i=0; i<n; i++)            scanf("%d", &midArray[i]);                int result = post(0, n-1, 0, n-1);        if(result){            for(int i =0; i<n-1; i++)                printf("%d ", postArray[i]);            printf("%d \n", postArray[n-1]);        }        else{             printf("No\n");        }    }    return 0;}

 

0 0