二叉树非递归遍历 javascript

本文详细介绍了如何使用栈实现二叉树的先序、后序和中序遍历。在先序遍历中,首先输出头节点,然后压入右孩子,再压入左孩子;后序遍历则通过unshift保存结果,并先压入左孩子,再压入右孩子;中序遍历需要找到左边界,依次处理节点并考虑右子树。这些方法展示了如何利用栈来模拟递归过程,实现不同遍历顺序。
摘要由CSDN通过智能技术生成

    首先要知道,递归遍历时系统会自动帮我们做入栈出栈操作,那么非递归时无非就是我们自己去调用栈。

.先序遍历最好理解:

    1.头节点入栈 

    2.弹栈,保存弹出的结果

    3.把刚刚弹出的节点的右节点和左节点压栈(先压右节点)

    4.重复2-3步直到栈空了

var preorderTraversal = function (root) {
    let arr=[],node=null,res=[]
    if(root==null) return res  //空树
    arr.push(root)
    while(arr.length!=0){
        node=arr.pop()  //原树或其子树根节点弹栈
        res.push(node.val) //弹出的值保存到结果
        if(node.right!=null) arr.push(node.right)  //先压栈右子树则其后出栈
        if(node.left!=null) arr.push(node.left)  //后压栈左子树则其先出栈
    }
    return res
};

对于大树及其任何一个子树,都遵循先输出头节点,再压入右孩子,再压入左孩子的规则。这里就保证了先序遍历中的头节点先输出。在弹栈时,由于任何两个左右子树都是左子树后进栈,所以左子树必然先出栈,这就实现了“头左右”的顺序。

二.后序

    后序是由先序的方法改进而来。改动有两点:1.保存出栈后的值不用push而是unshift,这样实现了输出结果数组时头节点的值总是在其子节点的后面。2.左右孩子入栈时先入左后入右,这样实现了在出栈时右孩子先被遍历,即右孩子在结果数组里的位置在左孩子后面。

var postorderTraversal = function(root) {
   let arr=[],node=null,res=[]
   if(root==null) return res
   arr.push(root)
   while(arr.length!=0){
       node=arr.pop() //根节点出栈
       res.unshift(node.val)  //出栈的根节点放结果数组最后
       if(node.left!=null) arr.push(node.left)  //先压栈左子树,则左子树后unshift进结果数组
       if(node.right!=null) arr.push(node.right)  //先压栈右子树,则右子树先unshift进结果数组
   }
   return res
};

三.中序

 中序的思路较前两个复杂一点:

  1.左边界上的全部节点入栈

  2.弹栈,保存弹出的结果

  3.刚刚弹出的节点若存在右子树,在该子树上执行1.,无右子树则执行2.

var inorderTraversal = function(root) {
    let arr=[],res=[],node=null
    if(root==null) return res
    while(root!=null||arr.length!=0){
        if(root!=null){  //分支一:每遇到一个节点先把其左边界压栈
            arr.push(root)
            root=root.left
        }else{  //分支二:左边界已压栈完,弹栈,每弹一个节点,就去保存值并处理该节点的右子树
            root=arr.pop()
            res.push(root.val)
            root=root.right  //存在右子树则进入分支一把左边界压栈,无右子树则进入分支二继续出栈
        }
    }
    return res
};

他是怎么实现中序遍历的:while里的事情可总结为:从左边界开始遍历(发生在弹栈时,此时保存的结果是“左头右”中的左),发现某节点有右子树后(此时该节点值已保存进结果,即“左头右”中的头),则转移到该右子树上,重复上述操作。直到遍历完某个右子树后继续遍历之前栈里的左边界。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值