1. 程式人生 > >PAT (Advanced Level) 1086 Tree Traversals Again (二叉樹構造及遍歷)

PAT (Advanced Level) 1086 Tree Traversals Again (二叉樹構造及遍歷)

 這題巨巨巨巨坑。一直以為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;
}