From 5cb33c319b8652f2694fccc9db88127ce5f24563 Mon Sep 17 00:00:00 2001 From: Arthur Date: Wed, 20 Oct 2021 16:10:04 +0100 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=200106.=E4=BB=8E=E4=B8=AD?= =?UTF-8?q?=E5=BA=8F=E4=B8=8E=E5=90=8E=E7=BB=AD=E9=81=8D=E5=8E=86=E6=9E=84?= =?UTF-8?q?=E9=80=A0=E4=BA=8C=E5=8F=89=E6=A0=91.md=20C=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...序与后序遍历序列构造二叉树.md | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/problems/0106.从中序与后序遍历序列构造二叉树.md b/problems/0106.从中序与后序遍历序列构造二叉树.md index 39b55d8c..9e0b2430 100644 --- a/problems/0106.从中序与后序遍历序列构造二叉树.md +++ b/problems/0106.从中序与后序遍历序列构造二叉树.md @@ -818,6 +818,81 @@ var buildTree = function(preorder, inorder) { }; ``` +## C +106 从中序与后序遍历序列构造二叉树 +```c +int linearSearch(int* arr, int arrSize, int key) { + int i; + for(i = 0; i < arrSize; i++) { + if(arr[i] == key) + return i; + } + return -1; +} + +struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize){ + //若中序遍历数组中没有元素,则返回NULL + if(!inorderSize) + return NULL; + //创建一个新的结点,将node的val设置为后序遍历的最后一个元素 + struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode)); + node->val = postorder[postorderSize - 1]; + + //通过线性查找找到中间结点在中序数组中的位置 + int index = linearSearch(inorder, inorderSize, postorder[postorderSize - 1]); + + //左子树数组大小为index + //右子树的数组大小为数组大小减index减1(减的1为中间结点) + int rightSize = inorderSize - index - 1; + node->left = buildTree(inorder, index, postorder, index); + node->right = buildTree(inorder + index + 1, rightSize, postorder + index, rightSize); + return node; +} +``` + +105 从前序与中序遍历序列构造二叉树 +```c +struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){ + // 递归结束条件:传入的数组大小为0 + if(!preorderSize) + return NULL; + + // 1.找到前序遍历数组的第一个元素, 创建结点。左右孩子设置为NULL。 + int rootValue = preorder[0]; + struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); + root->val = rootValue; + root->left = NULL; + root->right = NULL; + + // 2.若前序遍历数组的大小为1,返回该结点 + if(preorderSize == 1) + return root; + + // 3.根据该结点切割中序遍历数组,将中序遍历数组分割成左右两个数组。算出他们的各自大小 + int index; + for(index = 0; index < inorderSize; index++) { + if(inorder[index] == rootValue) + break; + } + int leftNum = index; + int rightNum = inorderSize - index - 1; + + int* leftInorder = inorder; + int* rightInorder = inorder + leftNum + 1; + + // 4.根据中序遍历数组左右数组的各子大小切割前序遍历数组。也分为左右数组 + int* leftPreorder = preorder+1; + int* rightPreorder = preorder + 1 + leftNum; + + // 5.递归进入左右数组,将返回的结果作为根结点的左右孩子 + root->left = buildTree(leftPreorder, leftNum, leftInorder, leftNum); + root->right = buildTree(rightPreorder, rightNum, rightInorder, rightNum); + + // 6.返回根节点 + return root; +} +``` + ----------------------- * 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) * B站视频:[代码随想录](https://space.bilibili.com/525438321)