前序+中序、中序+后序构造二叉树

https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/

https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/

前序+中序

  • 前序遍历,节点按照 [根左右] 排序。

  • 中序遍历,节点按照 [左根右] 排序。

所以,确定某根后,可以根据中序遍历判断该根的左右节点区间

在这里插入图片描述

通过结合前序遍历(确定根)中序遍历(确定根的左右子树),可以构造出二叉树。

class Solution {
public:
    int n, idx;
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        TreeNode* root = nullptr;
        n = inorder.size();
    
        return dfs(root, preorder, inorder, 0, n - 1);
    }

    // 获取根在中序遍历中的下标
    int index(int v, vector<int>& inorder) {
        for(int i = 0; i < n; i++)
            if(v == inorder[i])
                return i;
        return -1;
    }

    TreeNode* dfs(TreeNode* root, vector<int>& preorder, vector<int>& inorder, int l, int r) {
        if(l > r)
            return nullptr;
        
        int v = preorder[idx++];
        int ind = index(v, inorder);
        
        // 前序:根左右。和idx++同向
        // 中序:左根右。
        // 下面初始化时也是先左后右,和idx++同向
        root = new TreeNode(v);
        root->left = dfs(root->left, preorder, inorder, l, ind - 1);
        root->right = dfs(root->right, preorder, inorder, ind + 1, r);

        return root;
    }

};

中序+后序

和上面类似。

  • 后序遍历,节点按照 [左右根] 排序。

  • 中序遍历,节点按照 [左根右] 排序。

所以,确定某根后,也可以根据中序遍历判断该根的左右节点区间

代码区别也不大,需要注意的是idx的初值和构造顺序。后序遍历根是从后往前,即根右左,所以构造时也要符合这个顺序,先初始化再初始化

class Solution {
public:
    int idx, n;
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // idx初始值
        idx = n = inorder.size();
        TreeNode *root;
        return dfs(root, postorder, inorder, 0, n - 1);
    }

    // 获取根在中序遍历中的下标
    int index(int v, vector<int>& inorder) {
        for(int i = 0; i < n; i++)
            if(v == inorder[i])
                return i;
        return -1;
    }

    TreeNode* dfs(TreeNode* root, vector<int>& postorder, vector<int>& inorder, int l, int r) {
        if(l > r)
            return nullptr;
        int v = postorder[--idx];
        int ind = index(v, inorder);
        
        // 后序:左右根。和idx++同向
        // 中序:左根右。
        // 下面初始化时要按照先右后左的顺序,和idx++同向
        root = new TreeNode(v);
        root->right = dfs(root->right, postorder, inorder, ind + 1, r);
        root->left = dfs(root->left, postorder, inorder, l, ind - 1);
    
        return root;
    }
};
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用 C 语言设计的程序实现任意输入前序+中序序列生成唯一的二叉树,并打印其后序序列的功能: ```c #include <stdio.h> #include <stdlib.h> //定义二叉树结构体 typedef struct TreeNode { char data; //节点数据 struct TreeNode* left; //左孩子指针 struct TreeNode* right; //右孩子指针 } TreeNode; //根据前序中序序列生成二叉树 TreeNode* createTree(char* preorder, char* inorder, int size) { if (size <= 0) { //序列为空 return NULL; } TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); //创建根节点 root->data = *preorder; //根节点的值为前序遍历序列的第一个元素 int pos = 0; while (pos < size && inorder[pos] != root->data) { //在中序遍历序列中找到根节点的位置 pos++; } if (pos == size) { //无法找到根节点 printf("Error: Invalid Input!\n"); return NULL; } root->left = createTree(preorder + 1, inorder, pos); //递归构造左子 root->right = createTree(preorder + pos + 1, inorder + pos + 1, size - pos - 1); //递归构造右子 return root; } //后序遍历二叉树并打印节点值 void postorder(TreeNode* root) { if (root == NULL) { //为空 return; } postorder(root->left); //后序遍历左子 postorder(root->right); //后序遍历右子 printf("%c ", root->data); //输出当前节点的值 } //主函数 int main() { char preorder[] = {'A', 'B', 'D', 'E', 'C', 'F', 'G'}; //前序遍历序列 char inorder[] = {'D', 'B', 'E', 'A', 'F', 'C', 'G'}; //中序遍历序列 int size = sizeof(preorder) / sizeof(preorder[0]); //序列长度 TreeNode* root = createTree(preorder, inorder, size); //生成二叉树 if (root != NULL) { //二叉树生成成功 printf("Postorder: "); postorder(root); //后序遍历并打印二叉树 printf("\n"); } return 0; } ``` 程序的思路是:根据前序中序遍历序列来构造二叉树,然后后序遍历二叉树并打印节点值。程序中用到了递归的思想,具体解释如下: 1. 定义二叉树结构体 ```c typedef struct TreeNode { char data; //节点数据 struct TreeNode* left; //左孩子指针 struct TreeNode* right; //右孩子指针 } TreeNode; ``` 定义一个包含节点数据、左孩子指针和右孩子指针的结构体,表示二叉树的节点。 2. 根据前序中序序列生成二叉树 ```c TreeNode* createTree(char* preorder, char* inorder, int size) { if (size <= 0) { //序列为空 return NULL; } TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); //创建根节点 root->data = *preorder; //根节点的值为前序遍历序列的第一个元素 int pos = 0; while (pos < size && inorder[pos] != root->data) { //在中序遍历序列中找到根节点的位置 pos++; } if (pos == size) { //无法找到根节点 printf("Error: Invalid Input!\n"); return NULL; } root->left = createTree(preorder + 1, inorder, pos); //递归构造左子 root->right = createTree(preorder + pos + 1, inorder + pos + 1, size - pos - 1); //递归构造右子 return root; } ``` 在此函数中,首先判断序列是否为空,如果为空则返回 NULL。然后创建一个根节点,并将根节点的值设为前序遍历序列的第一个元素。接着在中序遍历序列中找到根节点的位置,如果无法找到根节点,则输出错误提示并返回 NULL。然后递归构造左子和右子,最后返回根节点。 3. 后序遍历二叉树并打印节点值 ```c void postorder(TreeNode* root) { if (root == NULL) { //为空 return; } postorder(root->left); //后序遍历左子 postorder(root->right); //后序遍历右子 printf("%c ", root->data); //输出当前节点的值 } ``` 该函数用于后序遍历二叉树并打印节点值。首先判断是否为空,如果为空则返回。然后递归后序遍历左子和右子,最后打印当前节点的值。 4. 主函数 ```c int main() { char preorder[] = {'A', 'B', 'D', 'E', 'C', 'F', 'G'}; //前序遍历序列 char inorder[] = {'D', 'B', 'E', 'A', 'F', 'C', 'G'}; //中序遍历序列 int size = sizeof(preorder) / sizeof(preorder[0]); //序列长度 TreeNode* root = createTree(preorder, inorder, size); //生成二叉树 if (root != NULL) { //二叉树生成成功 printf("Postorder: "); postorder(root); //后序遍历并打印二叉树 printf("\n"); } return 0; } ``` 在主函数中,定义前序遍历序列和中序遍历序列,计算序列长度,然后调用 createTree 函数生成二叉树,如果二叉树生成成功,则后序遍历并打印二叉树
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值