JavaScript二叉树遍历

4 篇文章 0 订阅

本文主要讲述二叉树的先序、中序、后序递归遍历及非递归遍历,并讲述如何使用JavaScript实现遍历逻辑。
下面,我们通过一个例子来回顾一下先序、中序、后序遍历:

二叉树

上面二叉树先序、中序、后序遍历结果分别为:
先序:ABCDEF
中序:CBDAEF
后序:CDBFEA

从上例可以总结出先序、中序、后序的规则:
先序:遍历到一个节点时,输出节点的值,然后遍历此节点的左子树,接着遍历此节点的右子树。
中序:遍历到一个节点时,先暂时存下来此节点,然后遍历此节点的左子树,然后输出节点的值,接着遍历此节点的右子树。
后序:遍历到一个节点时,先暂时存下来此节点,然后遍历此节点的左子树,接着遍历此节点的右子树,最后输出此节点的值。


JavaScript代码实现


开始讲述代码实现之前,先给出树节点构造函数:

function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
}

先序遍历


先序遍历递归实现
function prefaceTraverse(root){
    if(root!==null){
        console.log(root.val);
        prefaceTraverse(root.left);
        prefaceTraverse(root.right);
    }
}
先序遍历非递归实现
function prefaceTraverse(root){
    var stack = [];//定义一个暂时存储节点的栈
    var node = root;//定义一个游动节点
    //只要节点不为空,或者存储节点的栈不为空,就需要一直执行
    while(node!==null || stack.length >0){
        //只要节点不为空,根据先序遍历特点,一直向左走
        while(node !== null){
            console.log(node.val);//打印节点值
            stack.push(node);//把已经遍历打印的节点入栈
            node = node.left;//向左子树走
        }
        //上述循环跳出,说明,向左走走到叶节点了,若栈不为空
        //出栈一个节点,然后把node赋值为这个节点的右子树
        //接着就会继续从上述第一层循环开始遍历node的右子树
        if(stack.length >0){
            node = stack.pop();
            node = node.right;
        }
    }
}

中序遍历


中序遍历递归实现
function inOrderTraverse(root){
    if(root!==null){
        inOrderTraverse(root.left);
        console.log(root.val);
        inOrderTraverse(root.right);
    }
}
中序遍历非递归实现
function inOrderTraverse(root){
    var stack = [];//定义一个暂时存储节点的栈
    var node = root;//定义一个游动节点
    //只要节点不为空,或者存储节点的栈不为空,就需要一直执行
    while(node!==null || stack.length >0){
        //只要节点不为空,根据中序遍历特点,一直向左走
        while(node !== null){
            stack.push(node);//把节点入栈
            node = node.left;//向左子树走
        }
        //上述循环跳出,说明,向左走走到叶节点了,若栈不为空
        //出栈一个节点,然后打印出节点值
        //然后把node赋值为这个节点的右子树
        //接着就会继续从上述第一层循环开始遍历node的右子树
        if(stack.length >0){
            node = stack.pop();
            console.log(node.val);//打印节点值
            node = node.right;
        }
    }
}

后序遍历


后序遍历递归实现
function postOrderTraverse(root){
    if(root!==null){
        postOrderTraverse(root.left);
        postOrderTraverse(root.right);
        console.log(root.val);
    }
}
后序遍历非递归实现

后序遍历思想:
后序遍历和中序遍历不太一样,后序遍历判断当前节点是否可输出的条件是:当前节点的右子树是否遍历完成。
这个时候就需要我们增加一个变量lastNode去表标识上一个遍历的节点,若当前节点的右子树等于lastNode,说明就可输出当前节点。

function postOrderTraverse(root){
    var stack = [];//定义一个暂时存储节点的栈
    var node = root;//定义一个游动节点
    var lastNode = root;//标识上次遍历输出的节点
    //只要节点不为空,或者存储节点的栈不为空,就需要一直执行
    while(node!==null || stack.length >0){
        //只要节点不为空,根据先序遍历特点,一直向左走
        while(node !== null){
            stack.push(node);//把节点入栈
            node = node.left;//向左子树走
        }

        //出栈栈顶节点,若此节点的右子树已经遍历,或者为空
        //可以直接输出此节点
        node = stack[stack.length-1];
        if(node.right===null || node.right === lastNode){
            console.log(node.val);//打印节点值
            stack.pop();
            lastNode = node;
            node =null;
        }
        else{
            //继续遍历右子树
            node = node.right;
        }
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值