由二叉树的前序和中序还原二叉树

本文介绍了一种使用前序和中序遍历序列构建二叉树的方法,并通过递归实现了这一过程。此外,还提供了一个打印二叉树结构的函数,便于直观展示构建结果。
#include <stdio.h>
#include <stdlib.h>
///////////////////////////////////
typedef struct BiTreeNode
{
	char   value;
	struct BiTreeNode* lt;
	struct BiTreeNode* rt;
}BiTreeNode,BiTree;
void InitiateNode(BiTreeNode*&  p)
{
	p->value = '0';
	p->lt = NULL;
	p->rt = NULL;
}
BiTreeNode* BuildTree(char* pre, char* mid, int numOfNode)
{
	if(0 == numOfNode) return NULL;
	BiTreeNode* bt = (BiTreeNode*)malloc(sizeof(BiTreeNode));
	InitiateNode(bt);
	bt->value = pre[0];
	int i;
	for(i = 0; i < numOfNode; i++)
		if(mid[i] == pre[0]) break;
	bt->lt = BuildTree(pre+1, mid, i);
	bt->rt = BuildTree(pre+i+1, mid+i+1, numOfNode-i-1);
	return bt;
}
void Paint(BiTree* root, int n/*"n"为缩进的层数*/)/////打印
{
	int i;
	if(NULL == root) return;
	Paint(root->rt, n+1);/// 遍历打印右子树
	for(i = 0; i < 2*n-1; i++) printf(" ");
	if(n > 0)  printf("--%c\n",root->value);//输出有效值
	Paint(root->lt, n+1);
}
int main(void)
{
	int size;
	printf("请输入节点的个数:  ");
	scanf("%d",&size);
	//char pre[size];//前序序列
	//char mid[size];//中序序列
	char* pre; //前序序列
	char* mid;//中序序列
	pre = (char*)malloc(sizeof(char)*size);
	mid = (char*)malloc(sizeof(char)*size);
	printf("请输入前序序列:  ");
	scanf("%s",pre);
	printf("请输入中序序列: ");
	scanf("%s",mid);
	printf("%s\n",pre);
	printf("%s\n",mid);
	BiTree* root;
	root = BuildTree(pre, mid, size);
	printf("原二叉树是:\n");
	Paint(root, 2);//此处的5,只是是为了打印好看
	printf("\n");
	return 0;
}

### 算法原理 根据前序遍历遍历重建二叉树的核心思想是利用递归分治策略。前序遍历的第一个元素是二叉树的根节点,而在中遍历中找到该根节点后,可以将中列划分为左子树右子树两部分。通过递归处理左右子树,即可逐步构建出完整的二叉树。 具体步骤如下: 1. **确定根节点**:前序遍历的第一个元素即为当前子树的根节点。 2. **划分左右子树**:在中遍历中找到根节点的位置,其左侧为左子树的中遍历结果,右侧为右子树的中遍历结果。 3. **递归构建子树**:根据左子树右子树的节点数量,调整前序遍历的区间,并递归构建左右子树。 此方法的时间复杂度为 $O(n)$,其中 $n$ 为节点数量,空间复杂度也为 $O(n)$,主要由递归栈的空间消耗决定[^3]。 ### 实现代码 以下是一个基于 C++ 的实现示例: ```cpp struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; class Solution { public: TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { return build(preorder, inorder, 0, 0, inorder.size() - 1); } private: TreeNode* build(vector<int>& preorder, vector<int>& inorder, int preStart, int inStart, int inEnd) { if (inStart > inEnd) return nullptr; // 创建当前子树的根节点 TreeNode* root = new TreeNode(preorder[preStart]); // 在中遍历中找到根节点的位置 int rootIndex = 0; for (int i = inStart; i <= inEnd; ++i) { if (inorder[i] == root->val) { rootIndex = i; break; } } // 计算左子树的节点数量 int leftSubtreeSize = rootIndex - inStart; // 递归构建左子树右子树 root->left = build(preorder, inorder, preStart + 1, inStart, rootIndex - 1); root->right = build(preorder, inorder, preStart + leftSubtreeSize + 1, rootIndex + 1, inEnd); return root; } }; ``` ### 示例说明 以 `preorder = [3,9,20,15,7]` `inorder = [9,3,15,20,7]` 为例: - 前序遍历第一个元素为 `3`,因此根节点为 `3`。 - 在中遍历中找到 `3`,左边是 `[9]`(左子树),右边是 `[15,20,7]`(右子树)。 - 递归处理左右子树,最终可还原出完整的二叉树结构。 ### 复杂度分析 - **时间复杂度**:$O(n)$,每个节点仅被访问一次。 - **空间复杂度**:$O(h)$,其中 $h$ 是树的高度,主要来源于递归调用栈。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值