** 递归遍历的做法:
// 1、确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
// 2、确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
// 3、确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
/**
* 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[]}
*/
// 一、递归的做法
// 1、确定递归函数的参数和返回值
// 2、确定终止条件
// 3、确定单层递归的逻辑
// var preorderTraversal = function (root) {
// let res = [];
// const dfs = function (root) {
// if (root === null) return;
// //先序遍历所以从父节点开始
// res.push(root.val);
// //递归左子树
// dfs(root.left);
// //递归右子树
// dfs(root.right);
// }
// //只使用一个参数 使用闭包进行存储结果
// dfs(root);
// return res;
// };
// 二、非递归——迭代
// 前序遍历:中左右
// 压栈顺序:右左中
var preorderTraversal = function (root) {
let stack = []; let res =[]
if (!root) return [];
while(root){
res.push(root.val)
// 因为栈是先进后出的 所有要先弹出左 应该先将右push进去
if(root.right){stack.push(root.right)}
if(root.left){stack.push(root.left)}
// 然后每次更新root 将root的val值放入res
root = stack.pop()
}
return res;
};
// 三、非递归
// 前序遍历:中左右
// 压栈顺序:右左中
//res用来存放最后的返回结果 stack用来存放临时
var preorderTraversal = function (root, res = []) {
const stack = [];
if (root) stack.push(root);
while (stack.length) {
const node = stack.pop();
if (!node) {
res.push(stack.pop().val);
continue;
}
if (node.right) stack.push(node.right); // 右
if (node.left) stack.push(node.left); // 左
stack.push(node); // 中
stack.push(null);
};
return res;
};