1. 程式人生 > >poj 2255 Tree Recovery 解題報告

poj 2255 Tree Recovery 解題報告

               

題目出處

題意:輸入兩組資料,分別是前序遍歷序列和中序遍歷序列,你需要編寫程式通過這兩組資料求出該樹的後序遍歷序列(前序序列 + 中序序列 = 後序序列

解法:遞迴

題目分析:

可以先按照用筆和紙的形式去推匯出後序序列。推導過程省略,在推導過程中我們會發現規律:

假設 前序序列是 A B E H F C G I

 中序序列是 H E B F A C I G (圖如下)

每一次從前序序列裡,按順序抽取出字母就能將中序序列分割,並根據中序遍歷的特性。分割後的兩部分分別是 左子樹 右子樹(注意,他們也是二叉樹!)

就像這樣:取A, 中序序列被分割為 左子樹:H E B F  右子樹 C I G

繼續取B,但是這次是對左子樹:H E B F

進行分割。 分割結果是: 左子樹:H E  右子樹  B F

直到不能再分割,遞迴會返回去到第一次使用 A 分割出來的 右子樹 裡繼續分割

上述整個過程都是遞迴,所以結合程式碼和用紙筆畫一次會更好理解

程式碼:

#include <stdio.h>#include <stdlib.h>typedef struct TreeNode{ char    data; struct TreeNode   *lchild; struct TreeNode   *rchild;} Node, *PNode;char     preorder[28];   //存放前序序列char     infix[28
];  //存放中序序列char    *Pr;void build(char *in, char *pr, PNode *tr);void postordertraversal(PNode T);int main()//先建樹、再後序遍歷輸出 PNode    T;  while(scanf("%s %s", &preorder[1], &infix[1]) == 2) {  build(&infix[1], &preorder[1], &T);  postordertraversal(T);  printf("\n"); } return    0;}void
build(char *in, char *pr, PNode *tr)
char    *p = in; Pr = pr; if (*in == 0) {  *tr = NULL;  return; } while (1) {  if (*in == *Pr)  {   (*tr) = (PNode)malloc(sizeof(Node));   (*tr)->data = *Pr;   *in = 0;   break;  }  in++; } Pr = Pr + 1; build(p, Pr, &(*tr)->lchild); build(in+1, Pr, &(*tr)->rchild);}void postordertraversal(PNode T)if (T == NULL)  return; postordertraversal(T->lchild); postordertraversal(T->rchild); printf("%c", T->data);}
這份程式碼有些東西需要注意:
  • 這裡使用到指標,其實可以不使用指標的,下面介紹的更精巧的解法就是用下標的。能儘量不用指標就儘量不用
  • 注意指向指標的指標在這裡的作用,這裡有講解

上面的解法是比較直接容易想到的,所以程式碼沒有很精巧。而這裡有份更好的解法!