原题地址: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 1005 using 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; }