根据前序+中序还原二叉树(C++超简单易懂代码)

二叉树构造与遍历

        学校oj的水题,但我花了一番心思简化了代码,喜出望外!懂得都懂😆

题目描述:

用一棵二叉树的前序遍历序和中序遍历序可以唯一确定一棵二叉树,这个算法的核心操作是根据前序遍历序,查找中序遍历序中根节点的位置,以确定左子树序列,根节点,和右子树序列。然后递归找到每个子树的根节点就可以完成二叉树的构造。

输入格式:每行输入为一棵非空二叉树的前序遍历序串和中序遍历序串(两串长度均不超过2000),前序遍历序和中序遍历序中间用一个空格隔开。 每个结点为一个字符(字母或数字),且不存在相同结点。

输出格式:对每行输入,输出对应二叉树的后序遍历序后换行

输入样例:
abc bac
ab ba
输出样例:
bca
ba

思路:

核心思想就是递归!但递归里面的奥妙需要大家慢慢品味喔~~~

一般的树无非就四种情况:

 由于是后序输出,即左子树-->右子树-->根节点,所以条件设置时就考虑子树是否有空的情况和递归的顺序问题。

结合代码:t==0表示该根节点无左子树(不执行),比如样例:ab ab

             

### 算法原理 根据前序遍历和中遍历重建二叉树的核心思想是利用递归分治策略。前序遍历的第一个元素是二叉树的根节点,而在中遍历中找到该根节点后,可以将中列划分为左子树和右子树两部分。通过递归处理左右子树,即可逐步构建出完整的二叉树。 具体步骤如下: 1. **确定根节点**:前序遍历的第一个元素即为当前子树的根节点。 2. **划分左右子树**:在中遍历中找到根节点的位置,其左侧为左子树的中遍历结果,右侧为右子树的中遍历结果。 3. **递归构建子树**:根据左子树和右子树的节点数量,调整前序遍历的区间,并递归构建左右子树。 此方法的时间复杂度为 $O(n)$,其中 $n$ 为节点数量,空间复杂度也为 $O(n)$,主要由递归栈的空间消耗决定[^3]。 ### 实现代码 以下是一个基于 C++ 的实现示例: ```cpp struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; class Solution { public: TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { return build(preorder, inorder, 0, 0, inorder.size() - 1); } private: TreeNode* build(vector<int>& preorder, vector<int>& inorder, int preStart, int inStart, int inEnd) { if (inStart > inEnd) return nullptr; // 创建当前子树的根节点 TreeNode* root = new TreeNode(preorder[preStart]); // 在中遍历中找到根节点的位置 int rootIndex = 0; for (int i = inStart; i <= inEnd; ++i) { if (inorder[i] == root->val) { rootIndex = i; break; } } // 计算左子树的节点数量 int leftSubtreeSize = rootIndex - inStart; // 递归构建左子树和右子树 root->left = build(preorder, inorder, preStart + 1, inStart, rootIndex - 1); root->right = build(preorder, inorder, preStart + leftSubtreeSize + 1, rootIndex + 1, inEnd); return root; } }; ``` ### 示例说明 以 `preorder = [3,9,20,15,7]` 和 `inorder = [9,3,15,20,7]` 为例: - 前序遍历第一个元素为 `3`,因此根节点为 `3`。 - 在中遍历中找到 `3`,左边是 `[9]`(左子树),右边是 `[15,20,7]`(右子树)。 - 递归处理左右子树,最终可还原出完整的二叉树结构。 ### 复杂度分析 - **时间复杂度**:$O(n)$,每个节点仅被访问一次。 - **空间复杂度**:$O(h)$,其中 $h$ 是树的高度,主要来源于递归调用栈。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值