<编程之美>3.9重建二叉树

给定一棵二叉树,前序遍历结果为:a b d c e f

                                中序遍历结果为:d b a e c g

二叉树为:

                      

</pre><pre name="code" class="cpp">#include <iostream>
using namespace std;

#define TREELEN 6

//定义节点
typedef struct node NODE;
struct node
{
	NODE* pLeft;
	NODE* pRight;
	char chValue;
};

//根据前序遍历和中旬遍历的重建函数
void Rebuild(char *pPreOrder, char *pInOrder, int nTreeLen, NODE** pRoot)
{
	// 防止输入的前序/中序数组为空,只要两个数组不为空,这个判断不起作用
	if(pPreOrder == NULL || pInOrder == NULL)
	{
		return;
	}
	
	// 新建一个节点pTemp,因为前序遍历第一个值就是中间节点,所以直接赋值给pTemp,这样pTemp就存储了中间节点
	NODE* pTemp = new NODE;
	pTemp->chValue = *pPreOrder;
	pTemp->pLeft = NULL;
	pTemp->pRight = NULL;

	// 将中间节点pTemp赋值给外部接口pRoot
	if(*pRoot == NULL)
	{
		*pRoot = pTemp;
	}

	// 递归的最终输出,当前序和中序数组长度均为1时,直接将节点输出即可
	if(nTreeLen == 1)
	{
		return ;
	}

	//  准备寻找左子树的长度,预设参数
	char* pOrgInOrder = pInOrder;
	char* pLeftEnd = pInOrder;
	int nTempLen = 0;

	//  左子树的长度
	while(*pPreOrder != *pLeftEnd)
	{
		if(pPreOrder == NULL||pLeftEnd == NULL)
		{
			return;
		}
		nTempLen++;

		//记录临时长度,以免溢出
		if( nTempLen > nTreeLen )
		{
			break;
		}
		pLeftEnd++;
	}
	
	int nLeftLen = 0;
	nLeftLen = int(pLeftEnd - pOrgInOrder);

	// 右子树长度通过总长度和左子树长度求出
	int nRightLen = 0;
	nRightLen = nTreeLen - nLeftLen - 1;

	//重建左子树
	if( nLeftLen > 0 )
	{
		Rebuild( pPreOrder + 1, pInOrder, nLeftLen, &((*pRoot)->pLeft) );
	}

	//重建右子树
	if( nRightLen>0 )
	{
		Rebuild(pPreOrder + nLeftLen + 1, pInOrder + nLeftLen +1, nRightLen , &((*pRoot)->pRight) );
	}



}

int main()
{
	char szPreOrder[TREELEN] = {'a','b','d','c','e','f'};
	char szInOrder[TREELEN]  = {'d','b','a','e','c','f'};

	NODE *pRoot = NULL;
	Rebuild(szPreOrder, szInOrder, TREELEN, &pRoot);
	

	return 0;
}
递归步骤分析:(红色代表左子树蓝色代表右子树,黑色是中间节点)

                                                   1.           前序遍历   ab dc e f

                                                                 中序遍历  d b a e c f    

2             (左) 前序遍历   bd                                                              (右)       前序遍历   ce  f

                          中序遍历   d b                                                                                中序遍历  e c  f

3         (左) 前序遍历    d           (右) 前序遍历    空            3  (左) 前序遍历  e         (右)前序遍历   f

                  中序遍历    d                       中序遍历    空                           中序遍历  e                    中序遍历   f

在1中,保存中间节点a,然后进入左右部分递归

在2(左)中,保存中间节点b;在2(右),保存中间节点e。然后进入各自的左右递归。

在3(左)(左)中,保存中间节点d;在3(左)(右)中,无节点,空。  在3(右)(左)中,保存中间节点e;在3(右)(右)中,保存中间节点f。

得到二叉树:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值