LeetCode二叉树:递归遍历&&迭代遍历&&层序遍历
递归遍历
- 前序遍历
/**
* 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[]}
*/
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 inorderTraversal = function(root) {
let res = []
const dfs = function(root) {
if(root === null) {
return;
}
dfs(root.left)
res.push(root.val)
dfs(root.right)
}
dfs(root)
return res
};
- 后序遍历
var postorderTraversal = function(root) {
let res = []
const dfs = function(root) {
if(root === null) {
return;
}
dfs(root.left)
dfs(root.right)
res.push(root.val)
}
dfs(root)
return res
};
迭代遍历Ⅰ
前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。
为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。
- 前序遍历
var preorderTraversal = function(root) {
let res = []
//注:这里不能写成{return;},写分号是dfs用来结束条件的,
if(root === null){
return res
}
let cur = null
const stack = [root]
while(stack.length) {
cur = stack.pop()
res.push(cur.val)
cur.right && stack.push(cur.right)
cur.left && stack.push(cur.left)
}
return res
};
- 后序遍历
先序遍历是 中左右 --> 调整代码左右顺序:中右左 --> 翻转result数组:左右中
后序遍历:左右中
var postorderTraversal = function(root) {
let res = []
if(root === null) {
return res
}
const stack = [root]
let cur = null
while(stack.length) {
cur = stack.pop()
res.push(cur.val)
cur.left && stack.push(cur.left)
cur.right && stack.push(cur.right)
}
return res.reverse()
};
- 中序遍历
中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中)
处理顺序和访问顺序是不一致的。
在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。
var inorderTraversal = function(root) {
let res = []
if(root === null) {
return 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.val)
cur = cur.right //右
}
}
return res
};
迭代遍历Ⅱ
这里的迭代遍历是统一迭代,因为前面的代码无法通过改一两行代码实现中序遍历
- 前序遍历
/*
前序遍历:中左右
压栈顺序:右左中
*/
var preorderTraversal = function(root) {
let 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
};
- 中序遍历
//# 中序遍历
/*
中序遍历:左中右
压栈顺序:右中左
*/
var inorderTraversal = function(root) {
let 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) //右
stack.push(node) //中
stack.push(null)
if(node.left) stack.push(node.left) //左
}
return res
};
- 后序遍历
/*
后续遍历:左右中
压栈顺序:中右左
*/
var postorderTraversal = function(root) {
let res = []
const stack = []
if(root) stack.push(root)
while(stack.length) {
const node = stack.pop()
if(!node) {
res.push(stack.pop().val)
continue
}
stack.push(node) //中
stack.push(null)
if(node.right) stack.push(node.right) //有
if(node.left) stack.push(node.left) //左
}
return res
};
层序遍历
var levelOrder = function(root) {
let res = [],queue = []
queue.push(root)
if(root === null) {
return res
}
while(queue.length) {
//记录当前层级节点数
let length = queue.length
//存放每一层的节点
let curlevel = []
for(let i=0;i<length;i++) {
let node = queue.shift()
curlevel.push(node.val)
node.left && queue.push(node.left)
node.right && queue.push(node.right)
}
//把每一层的结果放到结果数组
res.push(curlevel)
}
return res
}