面试题6:重建二叉树,输入某二叉树的前序遍历和中序遍历的结果,重建出该二叉树。

假设输入的前序遍历和中序遍历的结果中都不含重复数字。

例如:输入前序遍历序列{1,2,4,7,3,5,6,8},和中序遍历序列{4,7,2,1,5,3,8,6}

要求重建出该二叉树,并输出其头结点。

二叉树结点的定义如下:

struct BinaryTreeNode
{
	int 	        m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;	
}
思路分析:首先清楚这几种遍历的顺序,前序遍历:根左右;中序遍历:左根右;即前序遍历序列的第一个结点总是根结点。
中序遍历的根节点在中间,且根节点左侧序列是左子树的结点值,右侧序列是右子树的结点值。

所以首要任务是;找出根结点的值以及左子树结点的值和右子树结点的值。然后用递归的方法去完成。

c++代码实现:

BinaryTreeNode* Construct(int* preorder,int* inorder,int length)
{
	if(preorder == Null||inorder==Null||length<=0)
	{
		return Null;
	}
	return ConstructCore(preorder,preorder+length-1,inorder,inorder+length-1);
}

BinaryTreeNode* ConstructCore
(
	int* startPreorder,int* endPreorder,int* startInorder,int* endInorder
)
{
	//1.前序遍历的第一个数字是根结点的值。以此根结点来创建新的二叉树,只有根结点,左右子树为空。
	int rootValue = startPreorder[0];
	BinaryTreeNode* root = new BinaryTreeNode();
	root->m_nValue=rootValue;
	root->m_pLeft=root->m_pRight=Null;
	
	if(startPreorder ==endPreorder)
	{
		if(startInorder == endInorder && *startPreorder == *startInorder)
			return root;
		else
			throw std::exception("Invalid input.");
	}
	
	//2.在中序遍历中找到根结点的值,在遍历序列中划分出左、右子树对应的子序列。
	int* rootInodrer = startInorder;
	while(rootInodrer<=endInorder && *rootInodrer!=rootValue)
	{
		++rootInodrer;//找到根结点在中序遍历中的位置
	}
	
	if(rootInodrer == endInorder && *rootInodrer!=rootValue)
	{
		throw std::exception("Invalid input.");
	}
	
	int leftLength = rootInodrer - startInorder;
	int* leftPreorderEnd = startPreorder+leftLength;
	//把构建二叉树的大问题分解成构建左右子树的两个小问题。用递归的方式来解决。
	if(leftLength>0)//3.构建左子树
	{
		//新的左子树的前序遍历序列从(startPreorder+1)到(leftPreorderEnd)结束。实现了在遍历序列中对左右子树的划分。
		//新左子树的中序遍历序列从(startInorder)到(rootInodrer-1)结束。故可以用递归的方法来实现左子树的创建。
		
		root->m_pLeft = ConstructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInodrer-1);//递归调用来分别构建左右子树
	}
	if(leftLength<endPreorder-startPreorder)//4.构建右子树
	{
		//新的右子树的前序遍历序列从(leftPreorderEnd+1)到(endPreorder)结束。
		//新左子树的中序遍历序列从(rootInodrer+1)到(endInorder)结束。故可以用递归的方法来实现右子树的创建。
		root->m_pRight = ConstructCore(leftPreorderEnd+1,endPreorder,rootInodrer+1,endInorder);
	}
	return root;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值