【由二叉树的中序序列和前序序列(后序序列)重建二叉树】

一、回顾前、中、后序遍历

1.1、前序遍历

前序遍历:根左右
代码:

#include<iostream>
#include<vector>

using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode* right;
};
class Solution{
public:
    void preorder(TreeNode* root,vector<int>&nums){
    if(root == nullptr){
        return;
    }
    nums.push_back(root->val);
    preorder(root->left,nums);
    preorder(root->right,nums);
}

vector<int>preorderTra(TreeNode*root){
    vector<int>res;
    preorder(root,res);
    return res;
}
};

1.2、中序遍历

中序遍历:左根右
代码:

#include<iostream>
#include<vector>

using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode* right;
};
class Solution{
public:
    void inorder(TreeNode* root,vector<int>&nums){
    if(root == nullptr){
        return;
    }
    inorder(root->left,nums);
    nums.push_back(root->val);
    inorder(root->right,nums);
}

vector<int>inorderTra(TreeNode*root){
    vector<int>res;
    inorder(root,res);
    return res;
}
};

1.3、后序遍历

后序遍历:左右根
代码:

#include<iostream>
#include<vector>

using namespace std;

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode* right;
};
class Solution{
public:
    void postorder(TreeNode* root,vector<int>&nums){
    if(root == nullptr){
        return;
    }
    postorder(root->left,nums);
    postorder(root->right,nums);
    nums.push_back(root->val);
}

vector<int>postorderTra(TreeNode*root){
    vector<int>res;
    postorder(root,res);
    return res;
}
};

二、由前+中重建二叉树

假设条件:遍历序列中无重复元素
在这里插入图片描述
由于前序遍历是根左右的顺序,可以由前序序列确定根结点的值,再在中序序列中确定根结点的位置,为什么要确定根结点位置呢,因为中序遍历是左根右的顺序,根结点即为左右子树的分界点,而后对左子树和右子树进行同样的操作,这就是一个递归的过程。

拿着根结点的值去中序序列中定位时,可以通过两种方法:

  1. 每次都用指针进行遍历;
  2. 将中序序列装进哈希表中,其中键为根结点的值,值为根结点在中序中的下标。

具体代码如下:

#include<iostream>
#include<vector>
#include<unordered_map>

using namespace std;
struct TreeNode{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x): val(x),left(nullptr),right(nullptr){}
};
class Solution{
private:
    unordered_map<int,int>m;
public:
    TreeNode* buildhelper(vector<int>&preorder,vector<int>&inorder,int preleft,int preright,int inleft,int inright){
        if(preleft > preright){
            return nullptr;
        }
        //在前序中确定根结点
        int root_val = preorder[preleft];
        //在中序中定位根结点
        int root_index = m[root_val];
        //建树
        TreeNode* root = new TreeNode(root_val);
        //左子树
        root->left = buildhelper(preorder,inorder,preleft+1,root_index-inleft+preleft,inleft,root_index-1);
        //右子树
        root->right = buildhelper(preorder,inorder,root_index-inleft+preleft+1,preright,root_index+1,inright);
        return root;
    }
    TreeNode* buildTree(vector<int>&preorder,vector<int>&inorder){
        int num = inorder.size();
        //哈希表存储中序序列,便于定位根结点
        for(int i = 0; i < num; i++){
            m[inorder[i]] = i;
        }
        return buildhelper(preorder,inorder,0,num-1,0,num-1);
    }
};

三、由后+中重建二叉树

假设条件:遍历序列中无重复元素
在这里插入图片描述
和前+中同样的思路,具体代码如下:

#include<iostream>
#include<vector>
#include<unordered_map>

using namespace std;
struct TreeNode{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x): val(x),left(nullptr),right(nullptr){}
};
class Solution{
private:
    unordered_map<int,int>m;
public: 
    TreeNode* buildhelper(vector<int>&postorder,vector<int>&inorder,int postleft,int postright,int inleft,int inright){
        if(postleft > postright){
            return nullptr;
        }
        //在后序中找到根结点
        int root_val = postorder[postright];
        //在中序中定位根结点
        int root_index = m[root_val];
        //建树
        TreeNode* root = new TreeNode(root_val);
        //左子树
        root->left = buildhelper(postorder,inorder,postleft,root_index-inleft+postleft,inleft,root_index-1);
        //右子树
        root->right = buildhelper(postorder,inorder,root_index-inleft+postleft+1,postright-1,root_index+1,inright);
        return root;
    }
    TreeNode* buildTree(vector<int>&postorder,vector<int>&inorder){
        int num = inorder.size();
        for(int i = 0; i < num; i++){
            m[inorder[i]] = i;
        }
        return buildhelper(postorder,inorder,0,num-1,0,num-1);
    }
};
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用递归的思路来实现,具体步骤如下: 1. 根据后序序列的最后一个元素确定根节点; 2. 在中序序列中找到根节点的位置,根节点左边的序列为左子树的中序序列,右边的序列为右子树的中序序列; 3. 分别递归求解左子树和右子树的前序序列; 4. 将根节点放在左子树的前序序列和右子树的前序序列的前面。 下面是该算法的 C 语言实现: ```c #include <stdio.h> #include <stdlib.h> // 树的结构体定义 typedef struct TreeNode { int val; struct TreeNode* left; struct TreeNode* right; } TreeNode; // 根据后序序列中序序列构造二叉树 TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize) { if (inorderSize == 0 || postorderSize == 0) { return NULL; } // 根节点为后序序列的最后一个元素 int rootVal = postorder[postorderSize - 1]; TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); root->val = rootVal; root->left = NULL; root->right = NULL; if (inorderSize == 1) { return root; } // 在中序序列中找到根节点的位置 int rootIndex = 0; for (; rootIndex < inorderSize; rootIndex++) { if (inorder[rootIndex] == rootVal) { break; } } // 递归求解左子树和右子树的前序序列 root->left = buildTree(inorder, rootIndex, postorder, rootIndex); root->right = buildTree(inorder + rootIndex + 1, inorderSize - rootIndex - 1, postorder + rootIndex, postorderSize - rootIndex - 1); return root; } // 前序遍历二叉树 void preorderTraversal(TreeNode* root) { if (root == NULL) { return; } printf("%d ", root->val); preorderTraversal(root->left); preorderTraversal(root->right); } int main() { int inorder[] = {4, 2, 5, 1, 6, 3}; int postorder[] = {4, 5, 2, 6, 3, 1}; TreeNode* root = buildTree(inorder, 6, postorder, 6); printf("前序遍历结果:"); preorderTraversal(root); printf("\n"); return 0; } ``` 输出结果为: ``` 前序遍历结果:1 2 4 5 3 6 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值