105-LeetCode 根据前序+ 中序序列构造二叉树

该博客介绍了如何利用LeetCode的第105题,通过给定的前序和中序遍历序列来构建二叉树。文中详细解释了递归方法的思路,即根据前序遍历确定根节点,然后在中序遍历中找到根节点的位置,从而划分左右子树,并继续递归构建。最后展示了构建完成的二叉树的层序遍历结果。

文章目录


题目

从前序与中序遍历序列构造二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。

注意:你可以假设树中没有重复的元素。

例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:
3
/ \
9 20
/
15 7




法一:递归

思路
根据前序遍历可以知道根节点,根据根节点可以在中序序列中得到左子树 和 右子树 的中序序列
我们可以得到如下信息:

  • 先序序列------根节点的值
  • 中序序列------根节点所在的下标
  • 中序序列-----左子树的长度
  • 中序序列-----右子树的长度
    在这里插入图片描述

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <map>
#include <list>

using namespace std;

struct TreeNode
{
    int data;
    TreeNode * left;
    TreeNode * right;
    TreeNode(int value)
    {
        data = value;
        left = NULL;
        right = NULL;
    }
};


// 层序输出构建的二叉树
void PrintFromTopToBottom(TreeNode * root)
{
    if(root == NULL)
    {
        return;
    }

    list<TreeNode *> l;
    l.push_back(root);

    while(!l.empty())
    {
        TreeNode * temp = l.front();
        cout << temp->data << " ";
        l.pop_front();

        if(temp->left)
        {
            l.push_back(temp->left);
        }
        if(temp->right)
        {
            l.push_back(temp->right);
        }
    }
    cout << endl;
}


map<int , int> index;           // 存储中序遍历----数据 vs 下标


// 递归 
// 根据前序遍历可以知道根节点,根据根节点可以在中序序列中得到左子树 和 右子树 的中序序列
TreeNode * MyBuildTree(const vector<int> & preorder , const vector<int> & inorder , int preOrder_left , int preOrder_right , int inOrder_left , int inOrder_right)
{
    int size = preorder.size();
    // 可根据数据去知道下标
    for(int i = 0; i < size;++i)
    {
        index[inorder[i]] = i;
    }

    if(preOrder_left > preOrder_right)
    {
        return NULL;
    }

    // 先序遍历中根节点的下标
    int preOrder_root = preOrder_left;

    // 根节点的值
    int root_value = preorder[preOrder_root];
    TreeNode * root = new TreeNode(root_value);

    // 中序遍历中根节点的下标
    int inOrder_root = index[root_value];
    // 得到左子树的节点数目
    int size_left_subtree = inOrder_root - inOrder_left;

    // 先序遍历下标       根                          左                              右
    // 先序遍历     preOrder_left       preOrder_left + size_left_subtree       preOrder_right
    // 中序遍历下标       左                          根                              右
    // 中序遍历     inOrder_left                inOrder_root                    inOrder_right

    // 递归构造左子树,并连接到左节点
    root->left = MyBuildTree(preorder , inorder , preOrder_left + 1 , preOrder_left + size_left_subtree , inOrder_left , inOrder_root - 1);
    // 递归构造右子树,并连接到右节点
    root->right = MyBuildTree(preorder , inorder , preOrder_left + size_left_subtree + 1 , preOrder_right , inOrder_root + 1 , inOrder_right);

    return root;
}


// 递归
TreeNode * BuildTree(const vector<int> & preorder ,const vector<int> & inorder)
{
    if(preorder.empty())
    {
        return NULL;
    }

    int size = preorder.size();

    // 可根据数据去知道下标
    for(int i = 0; i < size;++i)
    {
        index[inorder[i]] = i;
    }
    
    return MyBuildTree(preorder , inorder , 0 , size - 1 , 0 , size -1);
}

int main()
{
    vector<int> preOrder;
    preOrder.push_back(8);
    preOrder.push_back(4);
    preOrder.push_back(9);
    preOrder.push_back(12);
    preOrder.push_back(2);
    preOrder.push_back(1);
    preOrder.push_back(5);
    
    vector<int> inOrder;
    inOrder.push_back(9);
    inOrder.push_back(4);
    inOrder.push_back(12);
    inOrder.push_back(8);
    inOrder.push_back(1);
    inOrder.push_back(2);
    inOrder.push_back(5);

    TreeNode * root = BuildTree(preOrder , inOrder);
    PrintFromTopToBottom(root);

    return 0;
}

采用层序遍历输出我们构建的二叉树,输出结果如下:

8 4 2 9 12 1 5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值