当前位置:   article > 正文

从前序中序遍历序列构造二叉树的迭代算法理解_前序中序构造二叉树 迭代法

前序中序构造二叉树 迭代法

力扣上这道题的大神的迭代解法不是特别好理解,比如 详细通俗的思路分析,多解法 的迭代算法,看着解法新颖,但是我看了大半天都吃不透。后来想到了一个关于栈的算法题,就是给定两个数组 A 和 B,A 代表的是元素入栈的顺序,问 B 的元素顺序是不是 A 的出栈顺序。可以说,理解了出栈顺序这道题,基本就理解了这个二叉树构造的迭代算法了。

数组 A :[1,2,3,4,5],数组 B1 :[5,4,3,2,1],B2:[4,5,3,2,1],B3 :[3,4,5,2,1]。数组 B1,B2,B3 均是数组 A 的合法出栈顺序。我们可以发现,每次都是从 A 里面拿元素放入栈中,然后看栈顶元素值是不是和数组 B 指针指向的值相等,相等则弹出,否则不断将数组 A 的元素入栈。

而构造树,相对出栈顺序而言,要复杂一点,首先它是二维的,再一个就是任一节点都和根节点一样,也代表了一棵树,具有递归属性。

  1. public static TreeNode build(int[] preArr, int[] inArr){
  2. if (preArr == null || inArr == null || preArr.length != inArr.length || inArr.length == 0)
  3. return null;
  4. int pre = 0, in = 0;
  5. TreeNode root = new TreeNode(preArr[pre++]), curRoot = root;
  6. Stack<TreeNode> s = new Stack<>();
  7. s.push(root);
  8. while (pre < preArr.length){
  9. if (s.peek().val == inArr[in]){
  10. while (!s.isEmpty() && s.peek().val == inArr[in]){
  11. curRoot = s.pop();
  12. in++;
  13. }
  14. curRoot.right = new TreeNode(preArr[pre++]);
  15. s.push(curRoot.right);
  16. curRoot = curRoot.right;
  17. } else {
  18. curRoot.left = new TreeNode(preArr[pre++]);
  19. s.push(curRoot.left);
  20. curRoot = curRoot.left;
  21. }
  22. }
  23. return root;
  24. }

我的理解如下:

  1. 1. while 不断遍历前序数组 (出栈题是遍历数组 A)
  2. 2. 每次都是先检查栈顶元素是不是等于中序指针指向的元素,然后根据情况入栈 (出栈题也是入栈前,检查栈顶元素是否
  3. 等于数组 B 指针指向的值)
  4. a. 不相等,说明前序数组指针指向的元素是栈顶元素的左子节点
  5. b. 相等,说明栈顶节点的左子树遍历完了或者为空
  6. c. 第二个 while 循环是针对某个节点子孙节点都没有右子树的情况
  7. 3. 出栈完了后,那么此时的前序元素是 curRoot 节点的右子节点 (出栈题是一维的,树是二维的,所以要用 curRoot
  8. 维持状态,至于为什么是右子节点看文中链接作者给出的反证法)
  9. 4. curRoot 的右子节点也需要入栈,然后 curRoot 指向这个右子节点继续遍历
  10. 5. 此时,等于完成了一轮根节点的所有左子树节点入栈的过程,入栈和出栈过程中关联节点。当 curRoot 指向某个节点
  11. 的右子树节点时,此时的 curRoot 就和 root 性质一样了,逻辑上是“递归”以它为“根”节点的子树遍历过程

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/691113
推荐阅读
相关标签
  

闽ICP备14008679号