- 递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中
构建二叉树
// Creating a binary tree
class TreeNode {
constructor(value) {
this.value = value
this.left = null
this.right = null
}
}
const root = new TreeNode(5)
root.left = new TreeNode(4)
root.right = new TreeNode(6)
root.left.left = new TreeNode(1)
root.left.right = new TreeNode(2)
前序遍历
-
前序遍历:中左右
-
入栈:中 - 右 - 左
- 中空节点不入栈
-
出栈:中 - 左 - 右
-
5入 - 5出 - 6、4入 - 4出 - 2、1入 - 1、2出 - 6出
-
中先进去也会先出来
-
要访问的元素和要处理的元素顺序是一致的,都是中间节点
-
// 入栈 中 -> 右 -> 左
// 出栈 中 -> 左 -> 右
const preorderTraversal = function (root) {
let res = []
if (!root) return res
// 根节点入栈
const stack = [root]
let cur = null
while (stack.length) {
// 出栈
cur = stack.pop()
// 存入res
res.push(cur.value)
// 先右后左入栈
cur.right && stack.push(cur.right)
cur.left && stack.push(cur.left)
}
return res
}
// Validating the preorderTraversal function
const expectedOutput = [1, 2, 4, 5, 3, 6, 7]
const result = preorderTraversal(root)
console.log('Expected Output:', expectedOutput)
console.log('Result:', result)
console.log('Validation:', JSON.stringify(result) === JSON.stringify(expectedOutput))
中序遍历
-
处理:将元素放进result数组中
-
访问:遍历节点
-
用指针的遍历来帮助访问节点,栈则用来处理节点上的元素
- 前序遍历中访问节点(遍历节点)和处理节点(将元素放进result数组中)可以同步处理,但是中序就无法做到同步!
-
判断有左节点就入栈,一直添加到没有
-
pan duan
-
5、4、1入 - 1、4出 - 2入 - 2、5出 - 6入 - 6出
// 入栈 左 -> 右
// 出栈 左 -> 中 -> 右
const inorderTraversal = function(root, res = []) {
const stack = [];
let cur = root;
while(stack.length || cur) {
if(cur) {
stack.push(cur);
// 左
cur = cur.left;
} else {
// --> 弹出 中
cur = stack.pop();
res.push(cur.value);
// 右
cur = cur.right;
}
};
return res;
};
后序遍历
-
思路:变更左右子节点的入栈顺序,最后结果reverse
-
do while 和 while 循环的结果是一样的
const postorderTraversal = function(root, res = []) {
if (!root) return res;
const stack = [root];
let cur = null;
do {
cur = stack.pop();
res.push(cur.value);
cur.left && stack.push(cur.left);
cur.right && stack.push(cur.right);
} while(stack.length);
return res.reverse();
};