如何利用前序遍历序列和中序遍历序列非递归的创建二叉树

非递归创建二叉树:前序遍历与中序遍历
本文介绍了如何利用前序遍历和中序遍历序列,非递归地创建二叉树。通过两个栈,一个用于存储节点,另一个存储节点在中序序列中的下标,实现这一过程。详细阐述了根据遍历序列判断节点左右子树的方法,并解释了为何与栈中元素比较下标的逻辑。最后,提供了参考代码。

  说到二叉树的创建,我们一般会想到用递归的方法,因为利用递归写的代码看起来很简洁,但是递归的使用也同样存在效率不够高的问题。所以这里我们要说的是如何利用前序遍历序列和中序遍历序列非递归的创建二叉树。
  思想:利用两个栈实现(当然也可以用一个栈,这里针对自己的数据类型设计),一个栈s用来存放树的各个结点,另一个栈isindex用来存放第一个栈中元素对应于中序序列中的下标。首先,我们先将根结点(即前序序列中的第一个元素)及其在中序序列中相应的下标分别入栈s和isindex,并将根结点置于当前结点。然后,从前序序列中首元素开始,依次比较相邻两个元素在中序序列中对应的下标,来确定后一个元素是当前结点的左子树还是右子树,具体有以下几种情况:
    1. index2 == -1 这是在中序序列中没找到前序序列中的元素,说明是遍历序列有问题,直接退出
    2. index1 > index2 前序序列中后一个元素在中序序列中相对较前的位置,说明后一个元素是当前结点的左子树
    3. index1 < index2 前序序列中后一个元素在中序序列中相对较后的位置,说明后一个元素是当前结点的右子树,至于是那棵右子树,还需对index2和栈isindex栈顶元素作循环比较
   说到这里就有一个疑问了:为什么index2要和isindex栈顶元素比较呢?首先我们得知道isindex2里面存的是什么,前面已经说过,isindex里面存的是已经创建好的部分树的结点在中序序列中的下标,根据中序遍历的特点:中序遍历左子树,访问根节点,中序遍历右子树,我们知道,中序序列中右结点总是在左结点以及根结点的后边,即右结点在中序序列中的下标要大于左结点和根结点的下标,所以要想知道index2所对应的元素是已创建好的部分树的哪一个结点的右孩子结点,我们需要循环比较index2和栈isindex的栈顶元素的结点,如果栈顶元素较index2小,则栈s和isindex同时出栈,并将出栈结点作为当前结点,直到两栈为空或者遇到第一个比index2大的元素(即我们循环的目的就是找到最后一个比index2小的元素,这样index2所对应的元素就是找到的元素的右孩子结点),此时index2对应的元素就是当

### 构建二叉树的理论基础 前序遍历序遍历可以唯一确定一棵不含重复元素的二叉树前序遍历的第一个元素总是根节点,在中序遍历中定位到这个根节点后,可以根据其位置划分出左子树右子树对应的区间[^1]。 ### C++ 实现构建二叉树 为了实现这一过程,定义了一个辅助函数用于递归地创建各个子树部分。下面展示完整的代码逻辑: ```cpp #include <vector> using namespace std; struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { if (preorder.empty() || inorder.empty()) return nullptr; // 前序遍历第一个值作为根节点 TreeNode* root = new TreeNode(preorder[0]); auto it = find(inorder.begin(), inorder.end(), preorder[0]); // 计算左子树长度 int leftSize = distance(inorder.begin(), it); // 利用迭代器截取向量片段来表示左右子树范围 vector<int> preLeft(preorder.begin() + 1, preorder.begin() + 1 + leftSize); vector<int> inLeft(inorder.begin(), it); vector<int> preRight(preorder.begin() + 1 + leftSize, preorder.end()); vector<int> inRight(it + 1, inorder.end()); // 递归构造左右子树并连接至根节点 root->left = buildTree(preLeft, inLeft); root->right = buildTree(preRight, inRight); return root; } ``` 此段程处理特殊情况即输入为空的情况;接着初始化根节点,并利用`find()`查找根节点在中序列中的位置从而计算左侧子树大小;最后分别获取四个新的子数组代表两个子树各自的前后序列表达形式以便进一步递归调用自身完成整棵树结构重建工作[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值