根据后序中序序列建树

博客介绍了两种根据中序后序序列建树的算法,原理是从后序序列选根节点存入树,遍历中序序列找根节点并划分左右子树,关键在于找根节点和确定中序序列遍历范围,还给出了相关代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

本题我写了两种算法来实现根据中序后序序列建树,但是原理其实大同小异,都是先从后序序列中去挑选根节点存入树中,再遍历中序序列找到根节点,根据找到的根节点位置去划分出左右子树。所以关键就是如何找到每次的根节点,以及如何确定出中序序列的遍历范围。

代码1

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
template <class T>
struct BiNode{
	T data;
	BiNode<T> *lchild;
	BiNode<T> *rchild;
};
template <class T>
class BiTree{
	private:
		BiNode<T> *Root;
//post和mid存储了后序和中序序列的信息,root为每次要存进去的根节点,
//start和end为中序序列遍历的起止位置。
//遍历中序序列是为了找到根节点,再根据它划分出左右子树,
//也就是确定下一次递归的根节点位置和中序序列遍历范围
		BiNode<T> *CreateByPostMid(vector<T> &post,vector<T> &mid,int root,int start,int end)
		{
			if(start>end)
			return NULL;
			BiNode<T> *p=new BiNode<T>;
			p->data=post[root];
			int i=0;
			for(i=start;i<=end;)
			{
				if(post[root]!=mid[i]) i++;
			    else break;
			}
	       //因为后序是先左后右再根,所以找左子树的根节点需要跳过右子树的结点个数
			p->lchild=CreateByPostMid(post,mid,root-(end-i)-1,start,i-1);
		   //而找右子树的根节点只需要减1
			p->rchild=CreateByPostMid(post,mid,root-1,i+1,end);
			return p;
		}
		
	public:
		BiTree(vector<T> &post,vector<T> &mid)
		{
			int n=post.size();
			Root=CreateByPostMid(post,mid,n-1,0,n-1);
		}
		void LevelOrder(int N)
		{
			if(Root==NULL)
			return;
			queue<BiNode<T> *> Q;
			Q.push(Root);
			while(!Q.empty())
			{
				BiNode<T> *p=Q.front();
				Q.pop();
				cout<<p->data;
				N--;
				if(N!=0) cout<<" ";
				if(p->lchild!=NULL)
				Q.push(p->lchild);
				if(p->rchild!=NULL)
				Q.push(p->rchild);
			}
		}
};
int main()
{
	int N,x;
	vector<int> v1,v2;
	cin>>N;
	for(int i=0;i<N;i++)
	{
		cin>>x;
		v1.push_back(x);
	}
	for(int i=0;i<N;i++)
	{
		cin>>x;
		v2.push_back(x);
	}
	
	BiTree<int> Tree(v1,v2);
	Tree.LevelOrder(N);
	return 0;
}

代码2

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
template <class T>
struct BiNode{
	T data;
	BiNode<T> *lchild;
	BiNode<T> *rchild;
};
template <class T>
class BiTree{
	private:
		BiNode<T> *Root;
//这里和上面其实差不多,只是记得不再是中序序列遍历的起始和结束位置,而是树的结点个数
//终止条件也有所不同,结束条件为n==0
		BiNode<T> *CreateByPostMid(vector<T> &post,vector<T> &mid,int root,int imid,int n)
		{
			if(n==0)
			return NULL;
			BiNode<T> *p=new BiNode<T>;
			p->data=post[root];
			int i=0;
			while(post[root]!=mid[imid+i]) i++;
			p->lchild=CreateByPostMid(post,mid,root-(n-i),imid,i);
			p->rchild=CreateByPostMid(post,mid,root-1,imid+i+1,n-i-1);
			return p;
		}
		
	public:
		BiTree(vector<T> &post,vector<T> &mid)
		{
			int n=post.size();
			Root=CreateByPostMid(post,mid,n-1,0,n);
		}
		void LevelOrder(int N)
		{
			if(Root==NULL)
			return;
			queue<BiNode<T> *> Q;
			Q.push(Root);
			while(!Q.empty())
			{
				BiNode<T> *p=Q.front();
				Q.pop();
				cout<<p->data;
				N--;
				if(N!=0) cout<<" ";
				if(p->lchild!=NULL)
				Q.push(p->lchild);
				if(p->rchild!=NULL)
				Q.push(p->rchild);
			}
		}
};
int main()
{
	int N,x;
	vector<int> v1,v2;
	cin>>N;
	for(int i=0;i<N;i++)
	{
		cin>>x;
		v1.push_back(x);
	}
	for(int i=0;i<N;i++)
	{
		cin>>x;
		v2.push_back(x);
	}
	
	BiTree<int> Tree(v1,v2);
	Tree.LevelOrder(N);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值