树 是一种经常用到的数据结构,用来模拟具有树状结构性质的数据集合。
二叉树是一种更为典型的树状结构。如它名字所描述的那样,二叉树是每个节点最多有两个子树的树结构,通常子树被称作“左子树”和“右子树”。
所谓的纵向遍历二叉树,通常指的是前序遍历、中序遍历、后序遍历。
下面会介绍这三种遍历中的递归写法与迭代写法。
迭代写法就是用一个栈来存下每次遍历的左右子节点。
假设树的定义如下:
// 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)
}
前序遍历
前序遍历的顺序就是:根节点 -> 左子节点 -> 右子节点
注意:栈是先入后出的,但是前序遍历是先遍历左子节点,再遍历右子节点,所以需要先把右子节点先入栈
那么前序遍历的 递归写法 与 迭代写法 如下:
// 递归
var preorderTraversal = functioån(root) {
let arr = []
const preNode = (point) => {
if (point) {
arr.push(point.val)
preNode(point.left)
preNode(point.right)
}
}
preNode(root)
return arr
};
// 迭代
var preorderTraversal = function(root) {
let arr = []
let stack = []
if (root) stack.push(root)
while (stack.length) {
let point = stack.pop()
arr.push(point.val)
if (point.right) stack.push(point.right)
if (point.left) stack.push(point.left)
}
return arr
};
中序遍历
中序遍历的顺序就是:左子节点 -> 根节点 -> 右子节点
那么中序遍历的 递归写法 与 迭代写法 如下:
// 递归
var inorderTraversal = function(root) {
let arr = []
const midRoot = (point) => {
if (point) {
midRoot(point.left)
arr.push(point.val)
midRoot(point.right)
}
}
midRoot(root)
return arr
};
// 迭代
var inorderTraversal = function(root) {
let arr = []
let stack = []
while(root || stack.length) {
while (root) {
stack.push(root)
root = root.left
}
root = stack.pop()
arr.push(root.val)
root = root.right
}
return arr
};
后序遍历
后序遍历的顺序就是:左子节点 -> 右子节点 -> 根节点
这里解析一下后序遍历的迭代写法: 同样是用一个栈来存遍历的左右子节点,跟前序与中序遍历不一样的是,这里我在存子节点的时候存多一个状态来记录,判断是否遍历过左右子节点了 默认是false,没有遍历过,当我们遍历过之后设置为 true
那么后序遍历的 递归写法 与 迭代写法 如下:
// // 递归
var postorderTraversal = function(root) {
let arr = []
const nextR = (point) => {
if (point) {
nextR(point.left)
nextR(point.right)
arr.push(point.val)
}
}
nextR(root)
return arr
};
// 迭代
var postorderTraversal = function(root) {
let arr = []
let stack = []
if (root) stack.push([root, false])
while(stack.length) {
let point = stack.pop()
if (point[1]) {
arr.push(point[0].val)
} else {
if (!point[0].left && !point[0].right) {
arr.push(point[0].val)
} else {
stack.push([point[0], true])
}
if (point[0].right) stack.push([point[0].right, false])
if (point[0].left) stack.push([point[0].left, false])
}
}
return arr
};
总结
以上就是二叉树的纵向遍历的几种写法。后续会继续出二叉树的横向遍历的几种常见的场景以及写法。