二叉树的遍历是算法中的绝对基本功,除了求树的高度,树的宽度,树节点数量,先序遍历序列,中序遍历序列等;还有后面的图的遍历,各种图的算法,prim,Dijkstra,DFS 算法等的基础
好在二叉树的遍历并不难,只需要掌握四种遍历方法就可以拿下
- 前序遍历
- 中序遍历
- 后序遍历
- 层次遍历
这篇文章分享的前序遍历
和中序遍历
的递归和非递归
的 JS 代码实现
准备数据
javascript
const data = [0, 1, 2, 3, 4, 5, 6, null];
const generateTree = (data, i) => {
if (!data[i]) return null;
const root = { value: data[i] };
root.left = generateTree(data, 2 * i);
root.right = generateTree(data, 2 * i + 1);
return root;
};
const tree = generateTree(data, 1);
这里用数组来生成二叉树的数据结构。生成的过程借助了完全二叉树的思想
假设一个节点的序号是 n,那么左子节点的序号就是 2n,右子节点的序号就是 2n+1
数组按照层次遍历的顺序来排列,最后生成的二叉树就是下面这个样子
6 是 3 的 左节点
前序遍历
递归
javascript
const preOrder = (root) => {
if (!root) return;
console.log(root.value);
preOrder(root.left);
preOrder(root.right);
};
代码很容易理解,主要逻辑是先输出当前节点,然后输出左子树,再输出右子树
javascript
preOrder(tree);
非递归
javascript
const preOrder2 = (root) => {
const stack = [];
let node = root;
while (stack.length !== 0 || node !== null) {
while (node !== null) {
console.log(node.value);
stack.push(node);
node = node.left;
}
const currentNode = stack.pop();
node = currentNode.right;
}
};
这是前序遍历的非递归代码,借助了栈这个辅助数据结构。
遍历的过程中,现访问当前节点,然后将当前节点入栈。之后再访问左子节点。如果左子节点为空,就弹出栈中的一个元素,并且访问弹出元素的右子节点。
中序遍历
递归
javascript
const InOrder = (root) => {
if (!root) return;
InOrder(root.left);
console.log(root.value);
InOrder(root.right);
};
代码很容易理解,主要逻辑是先输出左子树,然后输出当前节点,再输出右子树
javascript
InOrder(tree);
非递归
javascript
const InOrder2 = (root) => {
const stack = [];
// stack.push(root);
let node = root;
while (stack.length !== 0 || node !== null) {
while (node !== null) {
stack.push(node);
node = node.left;
}
const currentNode = stack.pop();
console.log(currentNode.value);
node = currentNode.right;
}
};
这是中序遍历的非递归代码,借助了栈这个辅助数据结构。
遍历的过程中,先将当前节点入栈,之后再访问左子节点。如果左子节点为空,就弹出栈中的一个元素,输出弹出的元素,然后将 node 值为弹出元素的右节点。
输出结果和递归一致。
总结
文章分享的前序遍历
和中序遍历
的递归和非递归
的 JS 代码实现。代码比较简单,就没做很多解释。
后序遍历的非递归代码比较复杂,放在下一篇文章里分享