前端小算法之二叉樹的縱向遍歷

樹 是一種常常用到的數據結構,用來模擬具備樹狀結構性質的數據集合。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
};複製代碼

總結

以上就是二叉樹的縱向遍歷的幾種寫法。後續會繼續出二叉樹的橫向遍歷的幾種常見的場景以及寫法。

相關文章
相關標籤/搜索