浅谈二叉树的前序,中序,后序,顺序遍历

前置知识 \(:\) 前序(根左右),中序(左根右),后序(左右根) , 顺序(从上到下,从左到右)

例子: 前序(1,2,3,4,5,6) , 中序(3,2,4,1,6,5) , 后序(3,4,2,6,5,1)

\(①\) \(:\) 已知二叉树的中序和后序遍历,求其的前序遍历.

先上代码吧

//post代表后序,in代表中序.

void pre(int root,int l,int r){
	if(l>r) return;
	int k = l;
	while(k<r&&in[k]!=post[root]) ++k;
	cout<<post[root]<<" ";
	pre(root-(r-k)-1,l,k-1);
	pre(root-1,k+1,r);
} 
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",&post[i]);
	for(int i=1;i<=n;++i)
		scanf("%d",&in[i]);
	pre(n,1,n);
	return 0;
}

\(①\) \(:\) 总的原理来将就是利用后序数组不断地找根 ; 利用中序数组将树分割,不断配合着后序数组找根.

\(②\) \(:\) while(k<r&&in[k]!=post[root]) ++k;这句在找上一次后序找出来的根在前序中的位置.

\(③\) \(:\) l,k-1代表这个根的左子树在中序的区间,同理k+1,r代表右子树(将树不断分割).

\(④\) \(:\) root-1是右子树根的位置,为什么? 因为后序遍历是左右根,根的前一位(右子树的最后一位)就是右子树的根;root-(r-k)-1是左子树根的位置,为什么? 根的位置减去右子树的长度(r-k),再左移一位就是左子树根(左子树最后一位),后序找根作用就在这里.

那么如何进行顺序遍历呢? 其实我们发现前序遍历中"根左右",先根再左右恰好是父子递进的关系,那么记录一个坐标,按照二叉树的性质将坐标由父辈传给子辈就好了(有些坐标对应的是虚点).再按坐标顺序输出就可得到顺序遍历.

struct node{
	int pos,val;
};
vector<node> ans;
bool cmp(node a,node b) {return a.pos < b.pos;}
void pre(int root,int l,int r,int id){
	if(l>r) return;
	int k = l;
	while(k<r&&in[k]!=post[root]) ++k;
	ans.push_back(node{id,post[root]});
	pre(root-(r-k)-1,l,k-1,id*2+1);
	pre(root-1,k+1,r,id*2+2);
} 
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",&post[i]);
	for(int i=1;i<=n;++i)
		scanf("%d",&in[i]);
	pre(n,1,n,0);
	sort(ans.begin(),ans.end(),cmp); 
	for(int i=0;i<ans.size();++i){
		cout<<ans[i].val;
		if(i != ans.size()-1) cout<<" ";
	}
	return 0;
}

\(②\) \(:\) 已知已知二叉树的中序和前序遍历,求其的后序遍历.

原理与 \(①\) 一样的,只是后序遍历要剪长度往前找根,前序遍历要加长度往后找根,而且因为左右根的顺序,所以输出放遍历之后.

void post(int root,int l,int r){
	if(l > r) return;
	int k = l;
	while(k<r&&in[k]!=pre[root]) ++k;
	post(root+1,l,k-1);
	post(root+(k-l)+1,k+1,r);
	cout<<pre[root]<<" ";	
} 
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",&pre[i]);
	for(int i=1;i<=n;++i)
		scanf("%d",&in[i]);
	post(1,1,n);//要注意此时开始的根是1,不是后序的n.
	return 0;
}

可见中序的重要性(前序,后序求中序是不确定的.

关于建树的话,前序后序根与左右递进的关系都可以建.

posted @ 2021-10-05 17:21  xqy2003  阅读(303)  评论(0)    收藏  举报