根据先序序列和中序序列构造二叉树

根据先序序列和中序序列构造二叉树,最关键是确认根节点 左子树和右子树在序列中的具体位置。

首先,对于先序序列,根节点总是第一个,然后在中序序列中寻找到该根节点的位置,该位置的左右两边便是该根节点的左右子树,这便是根据先序序列和中序序列构造二叉树的原理。利用该原理继续对左右子树进行递归,便可构造完整的二叉树。

我们将写一个构造二叉树的函数,传递参数为先序序列A中子树的起点A_b和中点A_e,中序序列B中子树的起点B_b和中点B_e,这样做的原因是我们要实现递归构造,比如一开始从整棵树的根节点出发,那么四个参数是A_b = 1, A_e = n, B_b =1, B_e =n,(即从A[1]到A[n],从B[1]到B[n])。此时A[ A_a ]为根节点,即root = &A[ A_a ],我们将在B中寻找到它的位置,然后记录下根节点相对B[ B_b ]的位置,什么意思呢,即找到 i 使 B[ B_b + i ].num = root -> num(我们是通过判断节点的值是否相等来寻找节点的),i 就是相对位置,那么在B中,根节点的左子树为从B[ B_b] 到 B[ B_b + i - 1 ],右子树为从B[ B_b + i + 1 ]到 B[ B_e ]。然后我们也将左右子树在A中的位置也确定下来,A[ A_b ]是根节点,这一点刚才已经说了,然后该根节点的左子树是从A[ A_b + 1 ]到A[ A_b + i ],右子树是从A[ A_b + i + 1 ]到A[ A_e ]。

比较麻烦的地方就是上面确定左右子树分别在序列中的起点和终点。= = 要细心点 

 

还有就是要利用相对位置 i 来判断左右子树是否为空的情况,我们知道 B_b + i 代表根节点在B中的位置,其左右就刚好是左右子树。但是,若B_begin + i == B_begin,则说明左子树为空,同理,若B_begin + i == B_end,则说明右子树为空,因此千万别忘了判断是否为空的情况。

^O^ 下面将给出c++代码

该函数的功能:调用该函数后,先序序列A中的节点的 left 和 right 指针都将正确指向其左右子节点

struct node{
	int num;
	struct node* left;
	struct node* right;
};

//里面放着按先序序列排序的节点
node A[LEN];	

//里面放着按中序序列排序的节点
node B[LEN];	

/***搜索根在B中相对B_begin的位置***/
void search(node* T, const int B_begin, const int B_end, int &location)
{
	for (int i = B_begin; i <= B_end; i++)
	{
		if (T->num == B[i].num){
			location = i - B_begin;
			break;
		}
	}
}

/***根据先序序列和中序序列构造二叉树***/
void build_tree(int A_begin, int A_end, int B_begin, int B_end)
{
	node* T = &A[A_begin];
	int i = 0;

	//记录根在B中相对B_begin的位置,即( B_begin + i )代表着根节点在B中的位置
	search(T, B_begin, B_end, i);	

	//A[A_begin + 1] 和 A[A_begin + i + 1]分别为左右子树的根节点
	//B是中序序列,( B_begin + i )代表着根节点的位置,左右子树位于它的左右两边,但是,若B_begin + i == B_begin,
	//则说明左子树为空,同理,若B_begin + i == B_end,则说明右子树为空,千万别忘了判断是否为空的情况。

	if(B_begin + i != B_begin )
		T->left = &A[A_begin + 1]; 
	else T->left = NULL;

	if( B_begin + i != B_end )
		T->right = &A[A_begin + i + 1];
	else T->right = NULL;

	//递归左子树,能递归的条件是B_Begin  < B_begin + i - 1; 
	//若 !( B_Begin  < B_begin + i - 1 ),此时剩一个节点,为叶子节点。又或者左子树为空

	if(B_begin < B_begin + i - 1) 
		build_tree(A_begin + 1, A_begin + i, B_begin, B_begin + i - 1);
	else{
		A[A_begin + i].left = NULL;
		A[A_begin + i].right = NULL;
	}

	//递归右子树,能递归的条件是B_Begin + i + 1 < B_end; 
	//若 !( B_Begin + i + 1 < B_end ),此时剩一个节点,为叶子节点。又或者右子树为空

	if(B_begin + i + 1 < B_end) 
		build_tree(A_begin + i + 1, A_end, B_begin + i + 1, B_end);
	else
	{
		A[A_end].left = NULL;
		A[A_end].right = NULL;
	}

}


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值