輸入前序遍歷序列字符串a,中序遍歷字符串b,輸出後序遍歷字符串。node
1.已知前序遍歷,中序遍歷求後序遍歷,常規作法是創建一棵樹。
2.用手算的話很簡單,將字符串a遍歷一遍,依次插入到樹中。ios
for(a[i] in a){ //插入a[i] int flag = 1;// 標誌位爲1表示a[i]還未插入 設置p指針指向根結點 while(flag){ if(a[i]比p指向的結點的字母 在b字符串 中的索引小){ if(p->left爲空){ 將a[i]插入到p->left位置 flag = 0; //a[i]插入完成,跳出循環 }else{ p指向p->left } } else{//a[i]比p指向的結點的字母 在b字符串 中的索引大 if(p->right爲空){ 將a[i]插入到p->right位置 flag = 0; //a[i]插入完成,跳出循環 }else{ p指向p->right } } } }
#include <bits/stdc++.h> using namespace std; typedef long long ll; struct node{ char val; node* left; node* right; }; node* root; string a,b; //若是c在x左邊,返回1 bool InLeft(char x, char c){ for(int i = 0;b[i]; ++i){ if(b[i] == x){ return 0; } if(b[i] == c){ return 1; } } return 0; //此句理解起來可忽略,刪掉牛客網編譯器會報錯。 } void insert(char c){ node* p = root; //flag爲1表示c未插入到樹中 int flag = 1; //爲即將插入的結點申請空間 node* newNode = (node*)malloc(sizeof(node)); newNode->left = NULL; newNode->right = NULL; newNode->val = c; while(flag){ //若是c 在當前結點p的左邊(在b中的相對位置) if(InLeft(p->val, c)){ //若是當前結點p的左子樹不爲空 if(p->left){ p = p->left; }else{ p->left = newNode; flag = 0; } }else{ if(p->right){ p = p->right; }else{ p->right = newNode; flag = 0; } } } } //後續遍歷的遞歸(偷懶)寫法,非遞歸得用棧 void dfs(node* root){ if(!root) return; if(root->left) dfs(root->left); if(root->right) dfs(root->right); cout << root->val; } int main() { ios::sync_with_stdio(false); while(cin >> a >> b){ root = (node*)malloc(sizeof(node)); //若是a字符串不爲空,將第一個字母設置爲根結點字母 if(a[0]) root->val = a[0], root->left = NULL, root->right = NULL; //遍歷a字符串後續字母,依次插入到樹中 for(int i = 1;a[i]; ++i){ insert(a[i]); } //後序遍歷輸出樹 dfs(root); cout << endl; } return 0; }