剑指 Offer 07. 重建二叉树(C语言)

剑指 Offer 07. 重建二叉树(C语言)

1. Title

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

详情:点击这里

2. Do it

2.1. version 0.1(success)

/*!
 * @file 07buildTree.c
 * @date 2021-08
 * @version 0.1
 * @author forbit
 * @brief 构建二叉树的时候采用分块的思想,拆分二叉树,更容易实现。
 * @details score 24-44ms 7.2-7.6MB
 */

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

struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){

    /*!
     * @brief
     * @param preorder 前序遍历的数组的指针
     * @param preorderSize 前序遍历的数组preorder的长度
     * @param inorder 中序遍历的数组
     * @param inorderSize 中序遍历的数组inorder的长度
     * @return 输出结构体指针,指向已经构建好的二叉树的根节点
     */
     
    //! 判断空
    if(preorderSize==0) return NULL;

    //! 初始化
    struct TreeNode* tree_p = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    tree_p->left = NULL; tree_p->right = NULL;
    tree_p->val = preorder[0];

    int *p_array=inorder;  //!< 用于表示暂时切割后的中序遍历的数组
    int *p_array_preorder=preorder;  //!< 用于表示暂时切割后的前序遍历的数组
    int p_num=preorderSize;  //!< 用于表示暂时切割后的数组的长度

    //! 二叉树
    buil_tree(  tree_p,
                p_array,
                p_num,
                p_array_preorder);

    return tree_p;
}

void buil_tree( struct TreeNode* tree_p,
                int *p_array,
                int p_num,
                int *p_array_preorder)
{
    /*!
     * @brief
     * @param tree_p 二叉树头的指针
     * @param p_array 表示暂时切割后的中序遍历的数组
     * @param p_num 表示暂时切割后的数组的长度
     * @param p_array_preorder 表示暂时切割后的前序遍历的数组
     * @return null
     */

    int root_index=0;  //!< 表示暂时的root在p_array中的索引
    for(int i=0; i<p_num; i++) if(p_array[i]==tree_p->val) root_index=i;

    //! 判断存在左子树
    if(root_index>0)
    {
        build_left( tree_p,
                    p_array,
                    p_num,
                    p_array_preorder);
    }
    //! 判断存在右子树
    if(root_index<p_num-1)
    {
        build_right( tree_p,
                    p_array,
                    p_num,
                    p_array_preorder,
                    p_num);
    }
}

void build_left(    struct TreeNode* tree_p,
                    int *p_array,
                    int p_num,
                    int *p_array_preorder)
{
    /*!
     * @brief
     * @param tree_p 二叉树头的指针
     * @param p_array 表示暂时切割后的中序遍历的数组
     * @param p_num 表示暂时切割后的数组的长度
     * @param p_array_preorder 表示暂时切割后的前序遍历的数组
     * @return null
     */

    int root_index=0;  //!< 表示暂时的root在p_array中的索引
    for(int i=0; i<p_num; i++) if(p_array[i]==tree_p->val) root_index=i;
    // 调试
    printf("have a left son\n");
    printf("p_array[0]:%d, p_num:%d,p_array_preorder[0]:%d,p_array_preorder:%d, tree->val(root):%d\n",p_array[0],p_num,p_array_preorder[0],p_num,tree_p->val);

    //! 开辟空间
    struct TreeNode* tree_left = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    tree_left->left=NULL; tree_left->right=NULL;
    tree_p->left=&tree_left->val;

    //! 给左子树赋值
    tree_left->val=p_array_preorder[1];

    //! 更新p_array, p_num,p_array_preorder
    for(int i=0; i<p_num; i++) if(p_array[i]==tree_p->val) root_index=i;
    p_array=&p_array[0];
    p_num=root_index;
    p_array_preorder=&p_array_preorder[1];
    // 调试
    printf("p_array[0]:%d, p_num:%d,p_array_preorder[0]:%d,p_array_preorder:%d, tree_left->val(root):%d\n",p_array[0],p_num,p_array_preorder[0],p_num,tree_left->val);

    //! 递归
    buil_tree(  tree_left,
                p_array,
                p_num,
                p_array_preorder);
}

void build_right(   struct TreeNode* tree_p,
                    int *p_array,
                    int p_num,
                    int *p_array_preorder)
{
    /*!
     * @brief
     * @param tree_p 二叉树头的指针
     * @param p_array 表示暂时切割后的中序遍历的数组
     * @param p_num 表示暂时切割后的数组的长度
     * @param p_array_preorder 表示暂时切割后的前序遍历的数组
     * @return null
     */

    int root_index=0;  //!< 表示暂时的root在p_array中的索引
    for(int i=0; i<p_num; i++) if(p_array[i]==tree_p->val) root_index=i;
    
    // 调试
    printf("have a right son\n");
    printf("p_array[0]:%d, p_num:%d,p_array_preorder[0]:%d,p_array_preorder:%d, tree->val(root):%d\n",p_array[0],p_num,p_array_preorder[0],p_num,tree_p->val);

    //!开辟空间
    struct TreeNode* tree_right = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    tree_right->left=NULL; tree_right->right=NULL;
    tree_p->right=&tree_right->val;
    //! 给右子树赋值
    for(int i=0; i<p_num; i++) if(p_array[i]==tree_p->val) root_index=i;
    tree_right->val=p_array_preorder[root_index+1];

    //! 更新p_array, p_num,p_array_preorder
    p_array=&p_array[root_index+1];
    p_num=p_num-root_index-1;
    p_array_preorder=&p_array_preorder[root_index+1];

    //! 递归
    buil_tree(  tree_right,
                p_array,
                p_num,
                p_array_preorder);
}

posted @ 2021-08-24 19:14  forbit  阅读(137)  评论(0)    收藏  举报