PAT 1086 Tree Traversals Again


这一题的大意是说给出N个点,然后用栈的方式来建树,通过入栈和出栈的顺序来建立一棵二叉树,建立好树后,输出其后序遍历的序列。

我的思路是,根据题目中的入栈出栈,模拟建树,建好树后输出其后序遍历序列。

我刚开始采用的是用指针来构造树,比较麻烦,容易出错:

cpp 复制代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <limits.h>
#include <queue>
#include <string.h>
#include <stack>
using namespace std;
// 123456789
struct node
{
	int data;
	struct node* l;
	struct node* r;
}tree;
int N;
stack<int> stackk;
node* insert(int id,node* root)
{
	if(root==nullptr)
	{
		root=(node*)malloc(sizeof(node));
		root->data=id;
		root->l=nullptr;
		root->r=nullptr;
		return root;
	}
	else
	{
		if(root->l!=nullptr)
		{
		    root->l=insert(id,root->l);
		}
		else
		{
			root->r=insert(id,root->r);
		}
	}
}
node* dfsfind(node* root,int topid)
{
	if(root==nullptr)
	{
		return nullptr;
	}
	if(root->data!=topid)
	{
		if(root->l!=nullptr)
		{
			root=dfsfind(root->l,topid);
			if(root!=nullptr)
			{
				return root;
			}
		}
		
		if(root->r!=nullptr)
		{
			root=dfsfind(root->r,topid);
			if(root!=nullptr)
			{
				return root;
			}
		}
		
	}
	else
	{
		return root;
	}
}

void postorder(node* root)
{
	if(root==nullptr)
	{
		return ;
	}
	postorder(root->l);
	postorder(root->r);
	cout<<root->data<<" ";
	
}
int main()
{
	//ios::sync_with_stdio(0),cin.tie(0),cout.tie(
    cin>>N;
    node* root=nullptr;
    int topid=0;
    for(int i=0;i<2*N;i++)
    {
       string s;
	   int id;
	   cin>>s;
       if(s=="Push")
	   {
	   	    cin>>id;
			stackk.push(id);
            if(topid!=0)
            {
            	node* temp=dfsfind(root,topid);
            	temp=insert(id,temp);
            	cout<<temp->data<<endl;
            	topid=0;
			}
			else
			{
				root=insert(id,root);
			}
		}
		else
		{
			topid=stackk.top();
			stackk.pop();
			
		}
		
	}
	postorder(root);
	return 0;
 } 

这个代码不能通过。

对于PAT这种算法竞赛,在写树或者链表等数据结构的时候尽可能的用数组来模拟。这样的话比较方便,不容易写错,而且数组模拟可以直接获取下标,很方便。

于是:

cpp 复制代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <limits.h>
#include <queue>
#include <string.h>
#include <stack>
using namespace std;
// 123456789
struct node
{
   int data;
   int l;
   int r;
}; 
int N;
stack<int> st;
int cnt;
void postorder(vector<node> &tree,int root)
{
   if(root==-1)
   {
   	return ;
   }
   postorder(tree,tree[root].l);
   postorder(tree,tree[root].r);
   if(cnt!=0)
   cout<<" ";
   cout<<tree[root].data;
   cnt++;
}
int main()
{
   //ios::sync_with_stdio(0),cin.tie(0),cout.tie(
   cin>>N;
   vector<node> tree(N+1);
   for(int i=0;i<=N;i++)
   {
   	tree[i].l=-1;
   	tree[i].r=-1;
   	tree[i].data=-1;
   }
   int topid=0;
   string s;
   
   for(int i=0;i<N*2;i++)
   {
   	string s;
       int x;
       cin>>s;
       if(s=="Push")
       {
       	cin>>x;
       	st.push(x);
       	tree[x].data=x;
       	if(tree[topid].l==-1)
       	{
       		tree[topid].l=x;
   		}
   		else
   		{
   			tree[topid].r=x;
   		}
   		topid=x;	
   		
   	}
   	else
   	{
   		topid=st.top();
   		st.pop();
   	}
   }
   postorder(tree,1);
   
   return 0;
} 

但这有一个测试点不过原因是,我们不能错误的把1这个点当作根节点,因为有可能第一次输入可能不是1.

因此:

cpp 复制代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <limits.h>
#include <queue>
#include <string.h>
#include <stack>
using namespace std;
// 123456789
struct node
{
   int data;
   int l;
   int r;
}; 
int N;
stack<int> st;
int cnt;
void postorder(vector<node> &tree,int root)
{
   if(root==-1)
   {
   	return ;
   }
   postorder(tree,tree[root].l);
   postorder(tree,tree[root].r);
   if(cnt!=0)
   cout<<" ";
   cout<<tree[root].data;
   cnt++;
}
int main()
{
   //ios::sync_with_stdio(0),cin.tie(0),cout.tie(
   cin>>N;
   vector<node> tree(N+1);
   for(int i=0;i<=N;i++)
   {
   	tree[i].l=-1;
   	tree[i].r=-1;
   	tree[i].data=-1;
   }
   int topid=0;
   string s;
   bool hasroot=false;
   int root; 
   for(int i=0;i<N*2;i++)
   {
   	string s;
       int x;
       cin>>s;
       if(s=="Push")
       {
       	cin>>x;
       	//cout<<x<<endl;
       	if(hasroot==false)
       	{
       		hasroot=true;
       		root=x;
   		}
       	st.push(x);
       	tree[x].data=x;
       	//cout<<tree[x].data<<endl;
       	if(tree[topid].l==-1)
       	{
       		tree[topid].l=x;
   		}
   		else
   		{
   			tree[topid].r=x;
   		}
   		topid=x;	
   		
   	}
   	else
   	{
   		topid=st.top();
   		st.pop();
   	}
   }
   postorder(tree,root);
   
   return 0;
} 

成功通过

我在网上看到这一题还可以不建树来写

因为入栈顺序push恰好是前序遍历左右根,出栈顺序pop恰好是中序序列左根右,根据前序序列和中序序列是得到后序序列的:

原理

前序序列的第一个元素 = 根节点。

在中序序列中找到该根的位置:

左边部分 → 左子树的中序

右边部分 → 右子树的中序

在前序序列中,根之后的一段对应左子树,另一段对应右子树。

这样就能递归恢复二叉树。

得到树以后,再做一次后序遍历即可。

这里不详细叙述了。

有一道类似的题目:

已知后序遍历和中序遍历,求层次遍历:

PAT 1020 Tree Traversals

相关推荐
CoovallyAIHub3 小时前
中科大DSAI Lab团队多篇论文入选ICCV 2025,推动三维视觉与泛化感知技术突破
深度学习·算法·计算机视觉
NAGNIP3 小时前
Serverless 架构下的大模型框架落地实践
算法·架构
moonlifesudo4 小时前
半开区间和开区间的两个二分模版
算法
moonlifesudo4 小时前
300:最长递增子序列
算法
CoovallyAIHub9 小时前
港大&字节重磅发布DanceGRPO:突破视觉生成RLHF瓶颈,多项任务性能提升超180%!
深度学习·算法·计算机视觉
CoovallyAIHub9 小时前
英伟达ViPE重磅发布!解决3D感知难题,SLAM+深度学习完美融合(附带数据集下载地址)
深度学习·算法·计算机视觉
聚客AI1 天前
🙋‍♀️Transformer训练与推理全流程:从输入处理到输出生成
人工智能·算法·llm
大怪v1 天前
前端:人工智能?我也会啊!来个花活,😎😎😎“自动驾驶”整起!
前端·javascript·算法
惯导马工1 天前
【论文导读】ORB-SLAM3:An Accurate Open-Source Library for Visual, Visual-Inertial and
深度学习·算法
骑自行车的码农1 天前
【React用到的一些算法】游标和栈
算法·react.js