根据前序序列和中序序列重建二叉树

本文介绍了如何根据前序遍历和中序遍历的序列重建二叉树,基本思路是确定根节点,并寻找左右子树的分割点。在递归过程中需处理边界情况,如子树序列为空。同时,文章提到了C++中的vector操作技巧,如通过find()查找元素位置,以及使用构造函数初始化节点。最后,文中记录了一个编译错误及其原因,强调了遵循题目要求的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 基本思路:前序遍历的第一个节点为根节点,找到根节点在中序遍历中的位置i。然后分别找到前序遍历中左子树对应的部分,前序遍历中右子树对应的部分,中序遍历中左子树对应的部分,中序遍历中右子树对应的部分,分别用四个数组来存储。然后分别对左子树、右子树递归调用,传入的参数也对应发生改变。
2 代码实现:

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
     TreeNode* reConstructBinaryTree(vector<int>pre,vector<int>in) {
     //考虑边界情况:由于pre和in的size总是相同
     int inlen=in.size();
     if(inlen==0)
         return NULL;
     
     //先序遍历序列的首元素是根节点
     TreeNode * head=new TreeNode(pre[0]);
     //查找根节点在中序遍历序列中的位置,pos用来存储这个位置
     int pos=find(in.begin(),in.end(),pre[0])-in.begin();  
     //用left_pre存储前序序列中的左子树,left_in存储中序序列中的左子树
     //用right_pre存储前序序列中的右子树,right_in存储中序序列中的右子树
     vector <int> left_pre,left_in,right_pre,right_in;
     for(int i=0;i<pos;i++)
     {
         left_in.push_back(in[i]);
         left_pre.push_back(pre[i+1]);
     }
     for(int i=pos+1;i<inlen;i++)
     {
         right_in.push_back(in[i]);
         right_pre.push_back(pre[i]);
     }
     //将左子树的前序中序序列传入,递归构建左子树
     head->left=reConstructBinaryTree(left_pre,left_in);
     head->right=reConstructBinaryTree(right_pre,right_in);
         
     //每次递归调用返回根节点
     return head;
    }
};

3 注意事项:
①需要考虑边界情况,即当左子树序列或者右子树序列元素的个数为0的时候,返回值为空
②使用find()-in.begin()获取根元素在中序序列的位置,因为find()的返回值和begin()是同种类型,所以可以做运算。
③前序序列和中序序列分别对应的左子树和右子树的范围及更新是递归的前提
④每次递归调用都返回当前树的根节点。
4 语法收获:
①可以对vector的begin()和end()取内容(*)获得数组的首尾元素,注意end需要减1
②查找数组中是否有值为XX的元素并返回其下标
int i=find(a.begin(),a.end(),val)-a.begin()
使用find时添加头文件algorithm
find返回值是vector对应的迭代器类型,与begin()返回值类型相同,所以可以做运算
③ vector类型的好处是既可以通过指针访问,也可以通过下标访问
④不管是链表的节点还是树的节点,都可以在结构体内加一个构造函数,方便创建节点的时候直接初始化。
例如:
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
构造函数中使用参数列表初始化成员,注意参数列表的基本格式。
5 报错记录
编译报错:too few arguments to function call,expected 6,have 2
报错原因:形参和实参个数不符 收获:牛客网剑指offer的题目要严格按照它的定义来,因为是按照它的定义来测试用例的,如果修改,用例会因为参数传递不通过。

在C语言中,给定一棵二叉树的前遍历(根节点 -> 左子树 -> 右子树)序列遍历(左子树 -> 根节点 -> 右子树)序列,我们可以利用这两个线索重构该二叉树。这里是一个简单的步骤: 1. 首先,我们需要创建两个辅助函数: - `findRoot`:在中遍历中找到当前前遍历序列中的根节点。因为前遍历的第一个元素总是根节点,所以在中遍历中,它会出现在所有左子节点之前。 - `buildTree`:递归地根据序列构建二叉树。 2. 实现`findRoot`函数,它会返回中序列中对应前序序列根节点的位置。 3. 实现`buildTree`函数,输入是前序列、以及它们在当前序列中的位置。首先找到根节点,然后分别从左右子树部分的中序列剩余的前序序列中继续搜索。 4. 最终,当我们处理完整个前序列后,`buildTree`函数的结果将是我们需要的二叉树结构。 下面是一个简化的示例代码(由于实际二叉树结构复杂,这里只提供了一个基本思路,完整的代码实现可能会更长): ```c typedef struct TreeNode { char val; struct TreeNode *left; struct TreeNode *right; } TreeNode; TreeNode* buildTree(char* preorder, char* inorder, int preStart, int inStart, int inEnd) { if (preStart >= inEnd) return NULL; // 找到根节点 int rootIndex = findRoot(inorder, preorder[preStart], inStart, inEnd); // 构建当前节点 TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); root->val = preorder[preStart]; // 递归建立左子树右子树 root->left = buildTree(preorder, inorder, preStart + 1, inStart, rootIndex); root->right = buildTree(preorder, inorder, preStart + 1 + (rootIndex - inStart), rootIndex + 1, inEnd); return root; } int findRoot(char* inorder, char target, int start, int end) { while (start < end) { int mid = (start + end) / 2; if (inorder[mid] <= target) start = mid + 1; else end = mid; } return start; } ``` 注意:这个代码假设了前序列都是有效输入,并且每个字符都唯一表示一个节点值。在实际应用中,你需要额外处理这些边界情况错误检查。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值