PAT (Advanced Level) 1086 Tree Traversals Again (二叉樹構造及遍歷)
阿新 • • 發佈:2018-12-22
這題巨巨巨巨坑。一直以為Push結點就是從1至n的順序來的,交了之後只錯了一個case,而且報的是段錯誤,查了好久都不覺得什麼地方會有段錯誤啊,棧可能空的情況我已經檢查了,其餘的地方不可能會錯啊,最後改來改去錯誤還是定位在Push操作那段程式碼裡,既然棧不可能出錯,那剩下只可能是各個結點,而root和tmp結點都malloc過,而且全都確保會賦值,因此只有pre會有問題,最後想到萬一第一個Push的不是1,而我原來的程式碼預設第一個一定是1,這樣root就不會賦值給pre,應該只有這種情況了。遂更改。
這個bug想了很久的原因是隻有一個 case報了錯,導致我一直沒往那個方向想,這資料也有點坑爹。
思路:模擬Push和Pop的操作。pre表示上一個Push進來的結點,當pre這個結點還在stack中時,新Push進來的結點一定是pre的左孩子;如果pre已經不在stack中了,則是右子樹。而Pop操作中,如果pre和stack中第一個結點相同,表示這個結點可能還會有右子樹;不同則要麼右子樹已經遍歷構造結束,要麼沒有右子樹,因此pre指向此時stack中即將被pop的那個。
以及這題還有個做法,Push操作的順序其實是先序遍歷的順序,Pop操作出來相應的順序,實際是中序遍歷的順序。因此本質上還是先序中序求後序。
#include<bits/stdc++.h> using namespace std; typedef struct Node* PtrNode; struct Node{ int key; PtrNode lchild, rchild; }; int first = 0; void post_traversal(PtrNode x){ if(x == NULL) return; post_traversal(x->lchild); post_traversal(x->rchild); if(x->key != first) printf("%d ",x->key); else printf("%d",x->key); } int main(){ int n; scanf("%d",&n); string op; int key, cnt = 0; stack<PtrNode> stk; PtrNode root = (PtrNode)malloc(sizeof(struct Node)), pre; for(int i = 0; i < 2*n; ++i){ cin >> op; if(op == "Push"){ scanf("%d",&key); if(first == 0){ first = key; root->key = key; root->lchild = root->rchild = NULL; stk.push(root); pre = root; } else{ PtrNode tmp = (PtrNode)malloc(sizeof(struct Node)); tmp->key = key; tmp->lchild = tmp->rchild = NULL; if(!stk.empty() && pre->key == stk.top()->key){ pre->lchild = tmp; } else{ pre->rchild = tmp; } stk.push(tmp); pre = tmp; } } else{ if(stk.top()->key != pre->key){ pre = stk.top(); } stk.pop(); } } post_traversal(root); return 0; }