图解—由两种遍历方式建立二叉树

给你一个后序序列,你能想到什么?最后一个元素是根结点,的确是这样的,先序亦相似。

那么看到中序序列呢?似乎并不能看出什么,但你一定知道,根节点的左子树在中序遍历中一定在根节点的左边,右子树在其右边。

那么知道这些之后,可以干什么呢?

知道这些,你已经可以说一句狂话:如果能给我中序遍历和其他一种遍历,我能确定出根结点,还有它的左右子树!

那么还是不能得到完整的树结构啊?其实你已经回答了

既然你都能得到它的左右子树的两种遍历序列,那么为何不再做一遍,继续寻找它的根节点呢?

 

这样一看是不是突然觉得很容易

思路其实很简单,困难的是左右子树的划分。

根据后序和中序遍历建树的程序步骤:

    1、从后序遍历中取最后一个结点

    2、在中序遍历中找到该结点

    3、以该结点为界线,将中序遍历一分为二,得到两个中序序列

    4、根据中序的分组,再回到后序遍历中将之一分为二,得到两个后序序列

    5、对于每个非空序列,回到第一步,继续执行

 

直接分割数组(新数组)比较直观,但是会浪费很多空间。

而对数组进行划分(确界),很容易出现失误。

下面直接给出划分的图片

对数组分割,可以参考:

https://blog.csdn.net/qq_40946921/article/details/88065631 

好的,以下是二叉树C语言代码: ```c #include <stdio.h> #include <stdlib.h> // 二叉树结构体 typedef struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; } TreeNode; // 先序遍历建立二叉树 TreeNode* createTreeByPreorder(int* preorder, int size, int* index) { if (*index >= size || preorder[*index] == -1) { // 判断是否到达数组末尾或者该节点为空节点 (*index)++; // 指针下移 return NULL; // 返回NULL } // 创建节点 TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); node->val = preorder[*index]; node->left = NULL; node->right = NULL; (*index)++; // 指针下移 // 递归创建左子树和右子树 node->left = createTreeByPreorder(preorder, size, index); node->right = createTreeByPreorder(preorder, size, index); return node; } // 中序遍历建立二叉树(递归方式) TreeNode* createTreeByInorderRecursive(int* inorder, int inStart, int inEnd, int* preorder, int* preIndex) { if (inStart > inEnd) { // 判断是否到达叶子节点 return NULL; } // 创建节点 TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); node->val = preorder[(*preIndex)++]; node->left = NULL; node->right = NULL; int inIndex; // 找到该节点在中序遍历中的位置 for (int i = inStart; i <= inEnd; i++) { if (inorder[i] == node->val) { inIndex = i; break; } } // 递归创建左子树和右子树 node->left = createTreeByInorderRecursive(inorder, inStart, inIndex - 1, preorder, preIndex); node->right = createTreeByInorderRecursive(inorder, inIndex + 1, inEnd, preorder, preIndex); return node; } // 中序遍历建立二叉树(非递归方式) TreeNode* createTreeByInorderIterative(int* inorder, int size, int* preorder) { TreeNode* stack[size]; // 栈 int top = -1; // 栈顶指针 int preIndex = 0; // 先序遍历数组指针 // 创建根节点 TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); root->val = preorder[preIndex++]; root->left = NULL; root->right = NULL; TreeNode* node = root; // 遍历先序遍历数组 while (preIndex < size) { // 左子树 if (node->val != inorder[top + 1]) { // 创建节点并入栈 node->left = (TreeNode*)malloc(sizeof(TreeNode)); node->left->val = preorder[preIndex++]; node->left->left = NULL; node->left->right = NULL; stack[++top] = node; node = node->left; } // 右子树 else { top++; // 创建节点并出栈 while (top <= size - 2 && inorder[top] == stack[top + 1]->val) { top++; } node = stack[top]; node->right = (TreeNode*)malloc(sizeof(TreeNode)); node->right->val = preorder[preIndex++]; node->right->left = NULL; node->right->right = NULL; node = node->right; } } return root; } // 后序遍历建立二叉树 TreeNode* createTreeByPostorder(int* postorder, int size, int* index) { if (*index < 0 || postorder[*index] == -1) { // 判断是否到达数组末尾或者该节点为空节点 (*index)--; // 指针下移 return NULL; // 返回NULL } // 创建节点 TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); node->val = postorder[*index]; node->left = NULL; node->right = NULL; (*index)--; // 指针下移 // 递归创建右子树和左子树(注意顺序) node->right = createTreeByPostorder(postorder, size, index); node->left = createTreeByPostorder(postorder, size, index); return node; } // 先序遍历打印二叉树 void preorderTraversal(TreeNode* root) { if (root == NULL) { return; } printf("%d ", root->val); preorderTraversal(root->left); preorderTraversal(root->right); } // 中序遍历打印二叉树 void inorderTraversal(TreeNode* root) { if (root == NULL) { return; } inorderTraversal(root->left); printf("%d ", root->val); inorderTraversal(root->right); } // 后序遍历打印二叉树 void postorderTraversal(TreeNode* root) { if (root == NULL) { return; } postorderTraversal(root->left); postorderTraversal(root->right); printf("%d ", root->val); } int main() { int n; // 结点个数 printf("请输入结点个数:"); scanf("%d", &n); int preorder[n]; // 先序遍历数组 int inorder[n]; // 中序遍历数组 int postorder[n]; // 后序遍历数组 printf("请输入先序遍历数组:"); for (int i = 0; i < n; i++) { scanf("%d", &preorder[i]); } printf("请输入中序遍历数组:"); for (int i = 0; i < n; i++) { scanf("%d", &inorder[i]); } printf("请输入后序遍历数组:"); for (int i = 0; i < n; i++) { scanf("%d", &postorder[i]); } int index = 0; // 先序遍历数组指针 printf("先序遍历建立的二叉树:"); TreeNode* root1 = createTreeByPreorder(preorder, n, &index); // 先序遍历建立二叉树 preorderTraversal(root1); // 先序遍历打印二叉树 printf("\n"); int preIndex = 0; // 先序遍历数组指针 printf("中序遍历建立的二叉树(递归方式):"); TreeNode* root2 = createTreeByInorderRecursive(inorder, 0, n - 1, preorder, &preIndex); // 中序遍历建立二叉树(递归方式) inorderTraversal(root2); // 中序遍历打印二叉树 printf("\n"); printf("中序遍历建立的二叉树(非递归方式):"); TreeNode* root3 = createTreeByInorderIterative(inorder, n, preorder); // 中序遍历建立二叉树(非递归方式) inorderTraversal(root3); // 中序遍历打印二叉树 printf("\n"); int index2 = n - 1; // 后序遍历数组指针 printf("后序遍历建立的二叉树:"); TreeNode* root4 = createTreeByPostorder(postorder, n, &index2); // 后序遍历建立二叉树 postorderTraversal(root4); // 后序遍历打印二叉树 printf("\n"); return 0; } ``` 其中,`createTreeByPreorder`函数用于先序遍历建立二叉树;`createTreeByInorderRecursive`函数用于中序遍历建立二叉树(递归方式);`createTreeByInorderIterative`函数用于中序遍历建立二叉树(非递归方式);`createTreeByPostorder`函数用于后序遍历建立二叉树。`preorderTraversal`函数用于先序遍历打印二叉树;`inorderTraversal`函数用于中序遍历打印二叉树;`postorderTraversal`函数用于后序遍历打印二叉树。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值