储备知识
什么是二叉树
引用维基百科的解释:
二叉树(英语:Binary tree)是每个节点最多只有两个分支(即不存在分支度大于2的节点)的树结构。通常分支被称作“左子树”或“右子树”。二叉树的分支具有左右次序,不能随意颠倒。
前、中、后序遍历是什么
通俗的说就是对于每一棵树,它树顶的位置在两个孩子的前面为前序遍历、中间为中序遍历、后面为后序遍历(孩子的顺序一定是左孩子在右孩子前面)。如上面的二叉树,对于 ABC 这个小树来说: ABC 为 前序遍历,BAC 为中序遍历,BCA 为后序遍历。
二叉树的实现方式
-
链式存储 通过链表结构来实现。基于链表结构,可以从每个几点找到其子节点。大部分二叉树都是通过链表来实现的。
-
顺序存储 通过数组的方式来实现。只适用于完全二叉树。父节点与子节点的索引关系为:
JavaScript递归实现
前序遍历
function pre(tree, fatherIndex) {
if (!tree[fatherIndex]) {
return;
}
console.log(tree[fatherIndex]);
let leftChildrenIndex = 2 * fatherIndex + 1;
let rightChildrenIndex = 2 * fatherIndex + 2;
pre(tree, leftChildrenIndex);
pre(tree, rightChildrenIndex);
}
中序遍历
function middle(tree, fatherIndex) {
if (!tree[fatherIndex]) {
return;
}
let leftChildrenIndex = 2 * fatherIndex + 1;
let rightChildrenIndex = 2 * fatherIndex + 2;
middle(tree, leftChildrenIndex);
console.log(tree[fatherIndex]);
middle(tree, rightChildrenIndex);
}
后序遍历
function next(tree, fatherIndex) {
if (!tree[fatherIndex]) {
return;
}
let leftChildrenIndex = 2 * fatherIndex + 1;
let rightChildrenIndex = 2 * fatherIndex + 2;
next(tree, leftChildrenIndex);
next(tree, rightChildrenIndex);
console.log(tree[fatherIndex]);
}
递归序
从上面的前、中、后遍历函数可以看出,递归模式写法完全一致,只是 console.log 的位置不一样,如此就实现了三种顺序的打印。这是为什么呢?答案就是递归序。
递归序,顾名思义就是递归的顺序。
那么是怎么用到递归序来解决前、中、后序遍历的呢?举个例,查看下图:
根据代码可知每个节点都会经过3次,而在这三次中,哪一次打印会决定是什么遍历;经过的线路如下:
这里每个节点会经过三次是因为函数在函数体内,调用了自己两次。