POJ 2255 -- Tree Recovery
阿新 • • 發佈:2018-02-14
思路 node 空字符 ble 字符 == 二叉樹遍歷 tab body Tree Recovery
。
返回值:成功則返回要查找字符第一次出現的位置,失敗返回NULL
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 16032 | Accepted: 9865 |
題意:
根據二叉樹的先序遍歷和中序遍歷,求後序遍歷。
解題思路:
1)遞歸(不建樹)
可以先按照用筆和紙的形式去推導出後序序列。推導過程省略,在推導過程中我們會發現規律:
假設 前序序列是 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 分割出來的 右子樹 裏繼續分割
上述整個過程都是遞歸,所以結合代碼和用紙筆畫一次會更好理解
char *strchr(const char* _Str,char _Val) 頭文件:#include <string.h> 功能:查找字符串_Str中首次出現字符_Val的位置 說明:返回首次出現_Val的位置的指針,返回的地址是被查找字符串指針開始的第一個與Val相同字符的指針,如果Str中不存在Val則返回NULL1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int maxn = 30; 5 6 7 void Build(char *a,char *b,char *s,int n) 8 {//a是先序遍歷,b是中序遍歷 9 if(n<=0) 10 return; 11 else{ 12 ///記錄根節點在中序遍歷中的位置 13 int k = strchr(b,a[0]) - b; 14 ///0~k-1為左子樹 15 Build(a+1,b,s,k); 16 ///k+1~n為右子樹 17 Build(a+k+1,b+k+1,s+k,n-k-1); 18 s[n-1] = a[0]; 19 } 20 } 21 22 int main() 23 { 24 char a[maxn],b[maxn]; 25 while(cin>>a>>b) 26 { 27 char ans[maxn]; 28 int len = strlen(b); 29 Build(a,b,ans,len); 30 ans[len] = 0;///加結束符 31 cout<<ans<<endl; 32 } 33 return 0; 34 }
2)二叉樹遍歷(建樹)
對二叉樹的 前序遍歷、中序遍歷、後序遍歷 均可以使用DFS來做,
均是自上而下、自左至右遍歷,區別在於打印節點的時機不同:
[前序遍歷] 從父節點進入時打印當前節點
[中序遍歷] 從左子樹返回時打印當前節點
[後序遍歷] 從右子樹返回時打印當前節點
1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 5 using namespace std; 6 const int STR_LEN = 27;//樹遍歷序列最大長度 7 const int NULL_CHAR = ‘\0‘;//空字符 8 9 ///結點結構 10 class Node{ 11 public: 12 char name;//節點名稱 13 Node *left;//左子樹根節點 14 Node *right;//右子樹根節點 15 Node():name(NULL_CHAR),left(NULL),right(NULL){}//初始化 16 ~Node() 17 { 18 name = NULL_CHAR; 19 delete left;left = NULL; 20 delete right;right = NULL; 21 } 22 }; 23 24 Node* createTree(char *pro,char *in,int n) 25 { 26 Node *root = new Node; 27 if(n <= 0) 28 { 29 return root; 30 }else{ 31 int k = strchr(in,pro[0]) - in;//找到根節點在中序遍歷中的位置 32 root->name = pro[0]; 33 root->left = createTree(pro+1,in,k); 34 root->right = createTree(pro+k+1,in+k+1,n-k-1); 35 return root; 36 } 37 } 38 39 void dfs(Node *root,char *output) 40 { 41 if(root == NULL) 42 { 43 return; 44 } 45 dfs(root->left,output); 46 dfs(root->right,output); 47 ///構造後序序列,從右子樹返回時把當前的結點放到序列末尾 48 output[strlen(output)] = root->name; 49 //或寫成: 50 //*(output+strlen(output)) = root->name; 51 } 52 53 int main() 54 { 55 char pro[STR_LEN],in[STR_LEN]; 56 while(cin>>pro>>in) 57 { 58 int len = strlen(in); 59 Node *root = createTree(pro,in,len); 60 char output[STR_LEN] = {NULL_CHAR};///一定要初始化為空 61 dfs(root,output); 62 output[len] = 0; 63 cout<<output<<endl; 64 delete root; 65 } 66 return 0; 67 }
POJ 2255 -- Tree Recovery