前端小算法之二叉树的纵向遍历

树 是一种常常用到的数据结构,用来模拟具备树状结构性质的数据集合。node

二叉树是一种更为典型的树状结构。如它名字所描述的那样,二叉树是每一个节点最多有两个子树的树结构,一般子树被称做“左子树”和“右子树”。数据结构


所谓的纵向遍历二叉树,一般指的是前序遍历、中序遍历、后序遍历。ide

下面会介绍这三种遍历中的递归写法与迭代写法。post

迭代写法就是用一个栈来存下每次遍历的左右子节点。this

假设树的定义以下:递归

 // Definition for a binary tree node.
 function TreeNode(val, left, right) {
    this.val = (val===undefined ? 0 : val)
    this.left = (left===undefined ? null : left)
    this.right = (right===undefined ? null : right)
 }复制代码

前序遍历

前序遍历的顺序就是:根节点 -> 左子节点 -> 右子节点it

注意:栈是先入后出的,可是前序遍历是先遍历左子节点,再遍历右子节点,因此须要先把右子节点先入栈io

那么前序遍历的 递归写法 与 迭代写法 以下:function

// 递归
 var preorderTraversal = functioån(root) {
    let arr = []
    const preNode = (point) => {
        if (point) {
            arr.push(point.val)
            preNode(point.left)
            preNode(point.right)
        }
    }
    preNode(root)
    return arr
 };
 
// 迭代
var preorderTraversal = function(root) {
    let arr = []
    let stack = []
    if (root) stack.push(root)
    while (stack.length) {
        let point = stack.pop()
        arr.push(point.val)

        if (point.right) stack.push(point.right)

        if (point.left) stack.push(point.left)
    }
    return arr
};复制代码

中序遍历

中序遍历的顺序就是:左子节点 -> 根节点 ->  右子节点class

那么中序遍历的 递归写法 与 迭代写法 以下:

// 递归
var inorderTraversal = function(root) {
    let arr = []
    const midRoot = (point) => {
        if (point) {
            midRoot(point.left)
            arr.push(point.val)
            midRoot(point.right)
        }
    }
    midRoot(root)
    return arr
};

// 迭代
var inorderTraversal = function(root) {
    let arr = []
    let stack = []
    while(root || stack.length) {
        while (root) {
            stack.push(root)
            root = root.left
        }
        root = stack.pop()
        arr.push(root.val)
        root = root.right
    }
    return arr
};复制代码

后序遍历

后序遍历的顺序就是:左子节点  ->  右子节点 -> 根节点

这里解析一下后序遍历的迭代写法: 一样是用一个栈来存遍历的左右子节点,跟前序与中序遍历不同的是,这里我在存子节点的时候存多一个状态来记录,判断是否遍历过左右子节点了 默认是false,没有遍历过,当咱们遍历过以后设置为 true

那么后序遍历的 递归写法 与 迭代写法 以下:

// // 递归
var postorderTraversal = function(root) {
    let arr = []
    const nextR = (point) => {
        if (point) {
            nextR(point.left)
            nextR(point.right)
            arr.push(point.val)
        }
    }
    nextR(root)
    return arr
};

// 迭代
var postorderTraversal = function(root) {
    let arr = []
    let stack = []
    if (root) stack.push([root, false])
    while(stack.length) {
        let point = stack.pop()
        if (point[1]) {
            arr.push(point[0].val)
        } else {
            if (!point[0].left && !point[0].right) {
                arr.push(point[0].val)
            } else {
                stack.push([point[0], true])
            }
            if (point[0].right) stack.push([point[0].right, false])
            if (point[0].left) stack.push([point[0].left, false]) 
        }
    }
    return arr
};复制代码

总结

以上就是二叉树的纵向遍历的几种写法。后续会继续出二叉树的横向遍历的几种常见的场景以及写法。

相关文章
相关标签/搜索