已知二叉树的两种遍历序列输出求另一种遍历序列

已知二叉树的后序与中序序列输出前序序列(先序)

分析:后序序列的最后一个总是根结点,在中序序列中找到这个根结点,就可以将中序序列分割为两部分,左边是左子树,右边是右子树。先序序列的输出顺序是根–>左子树–>右子树。假设后序序列存放在post[ ]数组中,中序序列存放在in[ ]数组中,postL和postR分别为后序序列的左端索引和右端索引,inL和inR分别为中序序列的左端索引和右端索引。二叉树的根为post[postR],所以只需要在中序序列中遍历,找到与根结点的值相同的索引,就可以把中序序列分割为左右子树两个部分。用变量k标识中序序列中根的索引,则左子树的结点数为numLeft=k-inL,所以左子树的后序序列起始索引为[postL,postL+numLeft-1],左子树的中序序列起始索引为[inL,inL+numLeft-1],右子树的后序序列起始索引为[postL+numLeft,postR-1],右子树的中序序列起始索引为[inL+numLeft+1,inR]。所以获取根结点之后输出,再用同样的方法遍历左子树的根结点再输出,再遍历右子树的根结点再输出,模拟了先序遍历的过程,就省去了建树的过程。

代码:

void pre(int postL,int postR,int inL,int inR){
	if(postL > postR) return ;
	int rootData = post[postR]; //获取根结点的data域
	printf("%d ",rootData);
	int k;
	for(int i=inL;i<=inR;i++){
		if(in[i] == rootData){
			k = i;
			break;
		}
	}
	int numLeft = k-inL;
	pre(postL,postL+numLeft-1,inL,inL+numLeft-1);
	pre(postL+numLeft,postR-1,inL+numLeft+1,inR);
}

测试用例:

输入:

  • 后序:2 3 1 5 7 6 4
  • 中序:1 2 3 4 5 6 7

输出:

  • 前序:4 1 3 2 6 5 7

已知二叉树的前序与中序序列输出后序序列(建树)

分析:前序序列的第一个总是根结点,在中序序列中找到这个根结点,就可以将中序序列分割为两部分,左边是左子树,右边是右子树。后序序列的输出顺序是左子树–>右子树–>根。假设先序序列存放在pre[ ]数组中,中序序列存放在in[ ]数组中,preL和preR分别为后序序列的左端索引和右端索引,inL和inR分别为中序序列的左端索引和右端索引。二叉树的根为pre[preR],所以只需要在中序序列中遍历,找到与根结点的值相同的索引,就可以把中序序列分割为左右子树两个部分。用变量k标识中序序列中根的索引,则左子树的结点数为numLeft=k-inL,所以左子树的先序序列起始索引为[preL+1,preL+numLeft],左子树的中序序列起始索引为[inL,inL+numLeft-1],右子树的先序序列起始索引为[preL+numLef+1,preR],右子树的中序序列起始索引为[inL+numLeft+1,inR]。所以获取根结点之后,后序遍历左子树,再后序遍历右子树,最后输出根结点的值,模拟了后序遍历的过程,就省去了建树的过程。

代码(不建树):

void post(int preL,int preR,int inL,int inR){
	if(inL>inR) return;
	int rootData = pre[preL]; //获取根结点的data域
	int k;
	for(int i=inL;i<=inR;i++){
		if(in[i] == rootData){
			k = i;
			break;
		}
	}
	int numLeft = k-inL;
	post(preL+1,preL+numLeft,inL,inL+numLeft-1);
	post(preL+numLeft+1,preR,inL+numLeft+1,inR);
	printf("%d ",rootData);
}

代码(建树):

node* post(int preL,int preR,int inL,int inR){
	if(inL>inR) return NULL;
	int rootData = pre[preL]; //获取根结点的data域
	int k;
	node* root = new node;
	root->data = rootData;
	for(int i=inL;i<=inR;i++){
		if(in[i] == rootData){
			k = i;
			break;
		}
	}
	int numLeft = k-inL;
	root->lchild = post(preL+1,preL+numLeft,inL,inL+numLeft-1);
	root->rchild = post(preL+numLeft+1,preR,inL+numLeft+1,inR);
	printf("%d ",rootData);
	return root;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值