剑指Offer面试题7:重建二叉树

本文介绍了一种使用C++实现的方法,通过给定二叉树的前序遍历和中序遍历结果,递归地重建二叉树结构。关键步骤包括找到根节点、划分左右子树并递归处理。
摘要由CSDN通过智能技术生成

题目:输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如,输入前序遍历序列{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_pNight;

}

#include<iostream>
using namespace std;

struct BinaryTreeNode
{
	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

BinaryTreeNode* Structure(int* sPreorder, int* ePreorder, int* sInorder, int* eInorder)
//构建函数传入四根指针:前序&中序遍历的开始和结束指针
{
	int rootValue = sPreorder[0]; //定义根节点的值
	BinaryTreeNode* root = new BinaryTreeNode();  //创建二叉树结构体类型实例作为根节点
	root->m_nValue = rootValue;
	root->m_pLeft = root->m_pRight = nullptr;  //初始化

	if(sPreorder == ePreorder)
	{
		if(sInorder == eInorder && *sInorder == *eInorder)
			return root;
		else
			throw std::runtime_error("Invalid input");
	}
	
	int* rootInorder = sInorder;  //遍历中序序列找出根节点的值
	while(rootInorder <= eInorder && *rootInorder != rootValue)
	{
		++ rootInorder;
		if(rootInorder == eInorder && *rootInorder != rootValue)
		{
			throw std::runtime_error("Invalid input");
		}
	}
	
	int leftLen = rootInorder - sInorder;  //计算出左子树的长度,在前序遍历序列中分割出左子树和右子树的部分
	int* leftPreorderEnd = sPreorder + leftLen;
	if(leftLen > 0) //构建左子树
	{ 
		root->m_pLeft = Structure(sPreorder + 1, leftPreorderEnd, sInorder, rootInorder - 1);
	}
	if(ePreorder - leftPreorderEnd > 0) //构建右子树
	{
		root->m_pRight = Structure(leftPreorderEnd + 1, ePreorder, rootInorder + 1, eInorder);
	}
	return root;
}

void postOrderTraversal(BinaryTreeNode* root)  //后序遍历验证结果
{
    if (root == nullptr)
        return;

    postOrderTraversal(root->m_pLeft);
    postOrderTraversal(root->m_pRight);
    cout << root->m_nValue << " ";
}

int main()
{
    int preorder[] = {1, 2, 4, 7, 3, 5, 6, 8};
    int inorder[] = {4, 7, 2, 1, 5, 3, 8, 6};

    try  //如果在try块中发生了异常,程序会立即跳转到与之匹配的catch块,而不会继续执行try块中余下的代码
	{
        BinaryTreeNode* root = Structure(preorder, preorder + 7, inorder, inorder + 7);
        cout << "Postorder traversal: ";
        postOrderTraversal(root);
        cout << endl;
    }
	catch (std::exception& e) 
	{
        cout << "Exception occurred: " << e.what() << endl;
    }

    return 0;
}

解题思路:前序遍历(根左右),中序遍历(左根右),前序遍历第一个值为根节点,遍历中序序列找出该值,该值前面数字为左子树,后面数字为右子树,再去前序遍历中确定左右子树,然后递归,关键在于传入四根指针。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值