105. 从前序和中序遍历序列构造二叉树

题目描述

20201204234719

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

分析

二叉树前序遍历的顺序为:

  • 先遍历根节点;
  • 随后递归地遍历左子树;
  • 最后递归地遍历右子树。

二叉树中序遍历的顺序为:

  • 先递归地遍历左子树;
  • 随后遍历根节点;
  • 最后递归地遍历右子树。

在「递归」地遍历某个子树的过程中,我们也是将这颗子树看成一颗全新的树,按照上述的顺序进行遍历。挖掘「前序遍历」和「中序遍历」的性质,我们就可以得出根据前序和中序遍历构造二叉树的做法。

代码

struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
    struct TreeNode *newNode;
    int p = 0;
    int i = 0;

    // 去除输入不合理的情况
    if (preorder == NULL || inorder == NULL)
    {
        return NULL;
    }
    if (preorderSize <= 0 || inorderSize <= 0)
    {
        return NULL;
    }

    newNode = (struct TreeNode *) malloc(sizeof(struct TreeNode));
    newNode->val = preorder[p]; // 根据前序取出根节点
    newNode->left = NULL;
    newNode->right = NULL;

    for (i = 0; i < inorderSize; i++)
    {
        // 在中序中找到根节点,然后递归
        if (inorder[i] == newNode->val)
        {
            newNode->left = buildTree(&preorder[p + 1], i, inorder, i); // 递归构造左子树
            newNode->right = buildTree(&preorder[p + i + 1], preorderSize - i - 1, &inorder[i + 1],
                                       inorderSize - i - 1); // 递归构造右子树
            break;
        }
    }

    return newNode;
}

完整的测试代码

#include <stdio.h>
#include <malloc.h>

// Definition for a binary tree node.
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};

typedef struct TreeNode *BinTree;


struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize)
{
    struct TreeNode *newNode;
    int p = 0;
    int i = 0;

    // 去除输入不合理的情况
    if (preorder == NULL || inorder == NULL)
    {
        return NULL;
    }
    if (preorderSize <= 0 || inorderSize <= 0)
    {
        return NULL;
    }

    newNode = (struct TreeNode *) malloc(sizeof(struct TreeNode));
    newNode->val = preorder[p]; // 根据前序取出根节点
    newNode->left = NULL;
    newNode->right = NULL;

    for (i = 0; i < inorderSize; i++)
    {
        // 在中序中找到根节点,然后递归
        if (inorder[i] == newNode->val)
        {
            newNode->left = buildTree(&preorder[p + 1], i, inorder, i); // 递归构造左子树
            newNode->right = buildTree(&preorder[p + i + 1], preorderSize - i - 1, &inorder[i + 1],
                                       inorderSize - i - 1); // 递归构造右子树
            break;
        }
    }

    return newNode;
}

void freeTree(struct TreeNode *T)
{
    if (NULL == T)
        return;

    freeTree(T->left);
    freeTree(T->right);
    freeTree(T);
}

// 先序
void PreOrderTraversal(struct TreeNode *T)
{
    if (T) {
        printf("%d ", T->val);
        PreOrderTraversal(T->left);
        PreOrderTraversal(T->right);
    }
}

// 中序
void InOrderTraversal(struct TreeNode *T) {
    if (T) {
        InOrderTraversal(T->left);
        printf("%d ", T->val);
        InOrderTraversal(T->right);
    }
}

// 后序
void PostOrderTraversal(struct TreeNode *T) {
    if (T) {
        PostOrderTraversal(T->left);
        PostOrderTraversal(T->right);
        printf("%d ", T->val);
    }
}

// 测试
int main()
{
    int preorder[5] = {3, 9, 20, 15, 7};
    int inorder[5] = {9, 3, 15, 20, 7};

    BinTree buildedTree = buildTree(preorder, 5, inorder, 5);

    printf("前序遍历:");
    PreOrderTraversal(buildedTree);
    printf("
");
    printf("中序遍历:");
    InOrderTraversal(buildedTree);
    printf("
");
    printf("后序遍历:");
    PostOrderTraversal(buildedTree);

    return 0;
}

输出结果:

前序遍历:3 9 20 15 7 
中序遍历:9 3 15 20 7 
后序遍历:9 15 7 20 3 
原文地址:https://www.cnblogs.com/fanlumaster/p/14088280.html