题目简述
给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。
# 二叉树的先序、中序、后序遍历序列?
二叉树的遍历主要有三种:
(1)先(根)序遍历(根左右)
(2)中(根)序遍历(左根右)
(3)后(根)序遍历(左右根)
主要根据根节点的位置判断的。
举个栗子🌰:
左-蓝色,右-绿色,根-红色
示例
示例1:
输入: 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
};