二叉树理解起来也不难,一个根节点可以有左右两子树,而左右两个子树也可以有它们的子树。我们所比较陌生的,是如果要遍历每个元素,是一种怎样的遍历过程?
二叉树的常见遍历方法有前序,中序,后序遍历
图片源于B站教程
我这里介绍的是中序遍历的方法:
递归方法
先遍历左子树直到最后一个,输出C,
再遍历这个节点的右子树。由于示例中C节点没有右子树,则会回到它的上一级并输出根节点B,遍历B的右子树
由于D节点没有左子树,输出D,D也没有右子树,回到上一级输出A节点
这便是一个递归遍历的过程
var inorderTraversal = function (root) {
// res用于存放遍历过程的数组
const res = []
// rec为递归函数
const rec = (n) => {
// 如果n为空,则结束这次递归,并返回上一层递归
if (!n) return
rec(n.left)
res.push(n.val)
rec(n.right)
}
rec(root)
return res
};
迭代循环方法
这个方法需要引入栈的知识点,遵循后进后出的规则
遍历左子树,会把每一个节点推入栈中,当p指向null时,结束内层循环并将推出C,输出C。
将C节点右子树赋给p指针,用于C节点没有右子树,此时p为null,但栈的长度不为0,仍会继续循环。此时会推出B,输出B。在进入B的右子树,将D推入栈中
D没有左子树,将D推出,输出D
依次循环这个过程
var inorderTraversal = function(root) {
const res = [];
// 将stack看成一个栈的模型
const stack = [];
// p指针指向root根节点
let p = root;
// p不为null或者栈的长度不为0
while (p || stack.length) {
// 将所有节点的左节点全部推入栈中
while (p) {
stack.push(p);
p = p.left;
}
// 逐一访问每个节点及其右节点
const n = stack.pop();
res.push(n.val)
p = n.right;
}
return res
};