二叉树深度优先遍历-非递归实现

二叉树的具体构建详见此篇文章

一、先序遍历

1.算法思路

非递归遍历需要用栈实现。在先序遍历中,需要先将根节点压入栈中,然后不断对栈中的节点进行循环遍历。首先进行出栈操作,获取当前出栈节点的数据,之后将当前节点右孩子节点压入栈中(若存在),然后将左孩子节点压入栈中(若存在)。之后开始下一轮循环。
:因为栈是先进后出,所以先让右孩子进栈,这样下一轮循环时出栈的就是左孩子。(符合根左右的标准)
在这里插入图片描述

2.代码实现

  let preorderArr = []
  function preorder(node) {
    let stack = []
    stack.push(node)
    while (stack.length !== 0) { // 不断对栈中元素进行遍历
      let treeNode = stack.pop()
      preorderArr.push(treeNode.data); // 提取出栈节点数据
      if (treeNode.rChild) { // 后进先出,所以先压入右孩子节点
        stack.push(treeNode.rChild)
      }
      if (treeNode.lChild) {
        stack.push(treeNode.lChild)
      }
    }
  }
  console.log('先序:');
  preorder(tree)
  console.log(preorderArr);

运行结果:
在这里插入图片描述

二、中序遍历

1.算法思路

中序遍历时因为左孩子优先权最大,所以我们需要不断将当前节点压入栈中,然后去遍历其左孩子,只有当前节点的左孩子不存在时再进行退栈操作,去遍历其右孩子,直到当前栈为空且所有树节点全部被遍历。
在这里插入图片描述

2.代码实现

具体代码:

  // 中序非递归
  let inorderArr = []
  function inorder(node) {
    let stack = []
    let treeNode = node
    while (stack.length !== 0 || treeNode) { // 当前树的节点尚未遍历完,或者栈中数据不为空时,执行循环
      if (treeNode) { // 不断将每个节点压栈
        stack.push(treeNode)
        treeNode = treeNode.lChild
      } else { // 当左孩子不存在时则逐步退栈并遍历右子树
        treeNode = stack.pop()
        inorderArr.push(treeNode.data);
        treeNode = treeNode.rChild
      }
    }
  }
  console.log('中序:');
  inorder(tree)
  console.log(inorderArr);

运行结果:
在这里插入图片描述

三、后序遍历

1.算法思路

后续遍历其实有一个技巧。我们知道后序遍历其实是‘左右根’,如果我们将遍历的结果逆序获得的就是‘根右左’的遍历顺序。而我们上面的先序遍历代码中就有说到,当右孩子先进栈、左孩子后进栈则左孩子先出栈、先被遍历。所以我们只要调整这两句代码顺序就获得了‘根右左’的遍历顺序。,再将结果逆转就得到‘左右根’的后序遍历了。
在这里插入图片描述

2.代码实现

  // 后序非递归
  let postorderArr = []
  function postorder(node) {
    let stack = []
    stack.push(node)
    while (stack.length !== 0) {
      let treeNode = stack.pop()
      postorderArr.push(treeNode.data);
      if (treeNode.lChild) { // 与先序遍历相比,调整左、右孩子的进栈顺序
        stack.push(treeNode.lChild)
      }
      if (treeNode.rChild) { // 后进先出,所以先压入右子树
        stack.push(treeNode.rChild)
      }
    }
  }
  postorder(tree)
  console.log('后序:');
  console.log(postorderArr.reverse()); // 逆转最后的结果即得到后续遍历

运行结果:
在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值