PAT (Advanced Level) 1086 Tree Traversals Again (二叉树构造及遍历)

7 篇文章 0 订阅

 这题巨巨巨巨坑。一直以为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;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值