在 JavaScript 中,深度遍历(Depth-First Search, DFS)通常用于遍历树或图结构。深度遍历会沿着一个分支尽可能深地访问节点,直到到达叶子节点,然后再回溯到上一个节点,继续遍历其他分支。
以下是几种常见的深度遍历方法:
1. 递归实现
递归是实现深度遍历的最简单方法。以下是一个递归实现的深度遍历示例:
function dfs(node, callback) {
if (node === null) return;
// 访问当前节点
callback(node);
// 递归遍历子节点
if (node.children) {
for (let child of node.children) {
dfs(child, callback);
}
}
}
// 示例用法
const tree = {
value: 1,
children: [
{
value: 2,
children: [
{ value: 4, children: [] },
{ value: 5, children: [] }
]
},
{
value: 3,
children: [
{ value: 6, children: [] }
]
}
]
};
dfs(tree, node => console.log(node.value));
// 输出: 1, 2, 4, 5, 3, 6
2. 使用栈的非递归实现
递归方法虽然简单,但在处理深度较大的树时可能会导致栈溢出。可以使用栈来实现非递归的深度遍历。
function dfs(root, callback) {
if (root === null) return;
const stack = [root];
while (stack.length > 0) {
const node = stack.pop();
// 访问当前节点
callback(node);
// 将子节点逆序压入栈中,保证左子节点先被访问
if (node.children) {
for (let i = node.children.length - 1; i >= 0; i--) {
stack.push(node.children[i]);
}
}
}
}
// 示例用法
const tree = {
value: 1,
children: [
{
value: 2,
children: [
{ value: 4, children: [] },
{ value: 5, children: [] }
]
},
{
value: 3,
children: [
{ value: 6, children: [] }
]
}
]
};
dfs(tree, node => console.log(node.value));
// 输出: 1, 2, 4, 5, 3, 6
3. 前序、中序、后序遍历
对于二叉树,深度遍历可以分为前序遍历、中序遍历和后序遍历:
-
前序遍历:根节点 -> 左子树 -> 右子树
-
中序遍历:左子树 -> 根节点 -> 右子树
-
后序遍历:左子树 -> 右子树 -> 根节点
以下是二叉树的深度遍历实现:
class TreeNode {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}
// 前序遍历
function preOrder(node, callback) {
if (node === null) return;
callback(node.value);
preOrder(node.left, callback);
preOrder(node.right, callback);
}
// 中序遍历
function inOrder(node, callback) {
if (node === null) return;
inOrder(node.left, callback);
callback(node.value);
inOrder(node.right, callback);
}
// 后序遍历
function postOrder(node, callback) {
if (node === null) return;
postOrder(node.left, callback);
postOrder(node.right, callback);
callback(node.value);
}
// 示例用法
const root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
root.right.left = new TreeNode(6);
preOrder(root, value => console.log(value)); // 输出: 1, 2, 4, 5, 3, 6
inOrder(root, value => console.log(value)); // 输出: 4, 2, 5, 1, 6, 3
postOrder(root, value => console.log(value)); // 输出: 4, 5, 2, 6, 3, 1
总结
-
递归实现:简单直观,但可能栈溢出。
-
非递归实现:使用栈模拟递归,适合深度较大的树。
-
前序、中序、后序遍历:适用于二叉树的不同遍历顺序。
根据具体需求选择合适的遍历方法。