二叉树的遍历(JS)
二叉树的递归遍历(先序、中序、后序)
/**
* 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) {
const res = []
const preorder = function(root) {
// 终止条件
if(root === null) return
// 先序遍历, 中序、后序同理,调整顺序即可
res.push(root.val)
preorder(root.left)
preorder(root.right)
}
preorder(root)
return res
};
二叉树的迭代遍历(先序、中序、后序)
先分别将先序中序后序的迭代遍历代码贴在这里
先序迭代遍历
/**
* 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 = []
if(!root) return res;
// 定义递归栈
const stack = []
while(stack.length || root) {
if(root) {
stack.push(root)
res.push(root.val)
root = root.left
} else {
root = stack.pop()
root = root.right
}
}
return res
};
中序迭代遍历
/**
* 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 = []
if(!root) return res;
const stack = []
while(stack.length || root) {
if(root) {
stack.push(root)
root = root.left
} else {
root = stack.pop()
//与先序迭代遍历几乎一样,唯一的区别是将遍历语句移到了此处
res.push(root.val)
root = root.right
}
}
return res
};
后序迭代遍历
* 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 postorderTraversal = function(root) {
const res = []
const stack = []
let cur = root
// 与先序和中序遍历不同,由于后序遍历需要经过父节点两次,且操作不同,
// 因此需要定义一个前缀节点,以区分是第几次到达父节点。
let pre = null
while(stack.length || cur) {
if(cur) {
stack.push(cur)
cur = cur.left
} else {
cur = stack[stack.length - 1]
//判断是第一次到该节点还是第二次
if(cur.right && pre !== cur.right) {
//第一次到该节点
cur = cur.right
} else {
//第二次到该节点
stack.pop()
res.push(cur.val)
pre = cur
cur = null
}
}
}
return res
};
总结:
1.递归遍历可以采用几乎完全一样的模板,只需要调整遍历顺序即可;
2.迭代遍历中采用的模板大致相同,都依靠设置了一个辅助栈进行遍历,其中后序遍历还需要定义一个pre指针来区分是第几次经过父节点;
3.先序和中序迭代遍历仅有的区别在于什么时候将节点推入res数组,因此中序遍历相对先序遍历只改动了一行代码;
4.后序迭代遍历相对先序和中序在遍历左子树时操作相同,当遍历到父节点时需要判断是第一次还是第二次到达父节点,若第一次到达则继续遍历右子树,若是第二次则需要将节点值推入res数组并设置pre指针。