后序遍历 递归
var postorder= function (root, array = []) {
if (root) {
postorder(root.left, array);
postorder(root.right, array);
array.push(root.val);
}
return array;
};
后序遍历 非递归实现
//方法一:利用一个变量标记
var postorderTraversal = function (root) {
const result = [];//保存遍历顺序结果
const stack = [];
let last = null; // 标记上一个访问的节点
let current = root;
while (current || stack.length > 0) { //思路大概都一样:先找到最下面的左节点
while (current) {
stack.push(current);
current = current.left;
}
current = stack[stack.length - 1]; //是指向 而不是弹出
if (!current.right || current.right == last) {
//当 !current.right = true 即current.right=false 则当前节点没有右节点了可 直接读取打印当前节点了
//当current=last 时说明 右节点上一次已经访问过了,直接返回打印当前节点。
current = stack.pop();
result.push(current.val);
last = current;
current = null;
} else {
current = current.right; //如果有左节点 ,则回到一开始的while 继续以遍历当前节点为根节点,找到最下面的左节点。
}
}
return result;
}
//方法一:利用一个变量标记
var posOrderUnRecur = function(node) {
if(!node) {
return;
}
var stack = []
stack.push(node)
var tmp = null
while(stack.length !== 0) {
tmp = stack[stack.length - 1]
if(tmp.left && node !== tmp.left && node !== tmp.right) { //思路一样:都是找到最下面的左节点
stack.push(tmp.left)
} else if(tmp.right && node !== tmp.right) {
//当找到最下面的左节点是,看当前节点是否有右子树;有 则以当前右节点为根节点,继续找最下面左节点
stack.push(tmp.right)
} else {
//左右子树都遍历过了打印当前节点
console.log(stack.pop().value)
node = tmp //标记
}
}
}
// 方法二:使用两个栈
var postOrder = function(node) {
if(node) {
var s1 = []
var s2 = []
s1.push(node)
while(s1.length !== 0) {
node = s1.pop()
s2.push(node)
if(node.left) {
s1.push(node.left)
}
if(node.right) {
s1.push(node.right)
}
}
while(s2.length !== 0) {
console.log(s2.pop().value);
}
}
}
//方法三:使用一个栈 但是每次入栈是压入两次
//对于每个节点,都压入两遍。
//在循环体中,每次弹出一个节点赋给p,如果p仍等于栈的头结点,说明p的孩子们还没有被遍历,应该把它的孩子们加入栈中,否则,访问p。
//也就是说,第一次弹出,将p的孩子压入栈中,第二次弹出,访问p。
function postorder(root){
if(root == NULL) return [];
let arry = [];
let stack = [];
let p= root;
stack.push(p);
stack.push(p);
while(stack.length>0)
{
p = stack[stack.length-1]; //指向栈顶元素
stack.pop(); //弹出
if(stack.length>0&& p==stack[stack.length-1]) {//如果p等于栈的头结点,说明p的孩子们还没有被操作过
if(p.right){
stack.push(p.right);
stack.push(p.right);
}
if(p.left){
stack.push(p.left),
stack.push(p.left);
}
} else
arry.push(p.val);
}
return arry;
}
参考:
JS中的二叉树遍历详解