[路飞]_leetcode145. 二叉树的后序遍历

157 阅读2分钟

题目简述

leetcode145. 二叉树的后序遍历

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

# 二叉树的先序、中序、后序遍历序列?

二叉树的遍历主要有三种:

(1)先(根)序遍历(根左右)

(2)中(根)序遍历(左根右)

(3)后(根)序遍历(左右根)

主要根据根节点的位置判断的。

举个栗子🌰:

image.png 左-蓝色,右-绿色,根-红色 image.png

示例

示例1: image.png

输入: root = [1,null,2,3]
输出: [3,2,1]

示例2:

输入: root = []
输出: []

示例3:

输入: root = [1]
输出: [1]

提示:

  • 树中节点的数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100

JavaScript代码实现

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
// 左右根

//递归实现
function postorder(root,arr){
    if(root == null) return;
    postorder(root.left,arr);
    postorder(root.right,arr);
    arr.push(root.val)
}
var postorderTraversal = function(root) {
    // 递归遍历
    // let arr = []
    // postorder(root,arr);
    // return arr
    
    // 不用递归,迭代法, 模拟系统栈
    if(root == null) return [];
    // 1、第一个栈:存储相关节点地址,
    // 2、第二个栈:程序状态栈,记录当前压栈的状态; 标志当前这个节点是压入左子树还是压入右子树,还是根节点
    // 如需要压入左子树 状态为0, 右子树 状态为1,根节点 状态为2;
    let arr1 = []; // 实际就是压入递归过程中的局部变量
    let arr2 = []; // 递归的程序位置
    arr1.push(root);
    arr2.push(0); // 0 代表接下来要压入根节点的左子树,初始先处理左子树
    let result = []; // 存储最终输出结果
    // 当arr1不为空是,根据arr2的状态判断当前应该如何操作;
    while(arr1.length) {
        let status = arr2[arr2.length - 1];
        arr2.pop();
        switch(status){
            case 0: //左子树
                arr2.push(1);//目的:处理完左子树,记录准备处理右子树
                if(arr1[arr1.length-1].left !== null){ // 判断:当前节点是否有左子树, 如果有
                    arr1.push(arr1[arr1.length-1].left); // 将节点压入arr1中
                    arr2.push(0); // 目的:标记处理当前节点的左子树,~跟递归一个道理来~
                }
                break;
            case 1: //右子树
                arr2.push(2);// 目的:处理完右子树树,记录准备处理根节点
                if(arr1[arr1.length-1].right !== null){ // 判断:当前节点是否有右子树, 如果有
                    arr1.push(arr1[arr1.length-1].right); // 将节点压入arr1中
                    arr2.push(0); // 目的:标记处理当前节点的左子树,~跟递归一个道理来~
                }
                break;
            case 2: //根节点
                result.push(arr1[arr1.length-1].val);
                arr1.pop();
                break;
        }

    }
    return result

};

图例解析

二叉树遍历3.gif