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

相关推荐
离越词37 分钟前
C++day1作业
数据结构·c++·算法
凤年徐38 分钟前
【数据结构与算法】LeetCode 20.有效的括号
c语言·数据结构·算法·leetcode
医工交叉实验工坊2 小时前
R 语言 ComplexUpset 包实战:替代 Venn 图的高级集合可视化方案
算法·r语言
东皇太星3 小时前
模运算(密码学/数论/算法)
数据结构·算法·密码学
一水鉴天4 小时前
整体设计 修订 之1 三“先”之“基” 与范畴重构:康德先验哲学的批判性程序化实现
java·人工智能·算法
JuneXcy4 小时前
流程控制语句(3)
c语言·算法
Mercury_Lc5 小时前
【贪心 或 DFS - 面试题】小于n最大数
数据结构·c++·算法
凤年徐5 小时前
【数据结构】LeetCode160.相交链表 138.随即链表复制 牛客——链表回文问题
c语言·数据结构·c++·算法·leetcode·链表
qq_12498707535 小时前
基于改进蜂群优化算法的高频金融波动率预测系统 (源码+论文+部署+安装)
python·算法·金融·毕业设计·蜂群优化算法