Javascript 中的深度优先搜索遍历

javascriptweb developmentfront end technology

DFS 在访问兄弟顶点之前先访问子顶点;也就是说,它在探索任何特定路径的广度之前先遍历其深度。实现算法时通常使用堆栈(通常是程序通过递归调用的堆栈)。

以下是 DFS 的工作原理 −

  • 访问相邻的未访问顶点。将其标记为已访问。显示它。将其推入堆栈。
  • 如果未找到相邻顶点,则从堆栈中弹出一个顶点。 (它将弹出堆栈中所有没有相邻顶点的顶点。)
  • 重复规则 1 和规则 2,直到堆栈为空。

让我们看一下 DFS 遍历的工作原理。

步骤遍历描述
1Traversal初始化堆栈。
2Traversal 1S 标记为已访问并将其放入堆栈。从 S 探索任何未访问的相邻节点。我们有三个节点,我们可以选择其中任何一个。在此示例中,我们将按字母顺序获取节点。
3Traversal 2A 标记为已访问并将其放入堆栈。从 A 探索任何未访问的相邻节点。 SD 都与 A 相邻,但我们只关注未访问的节点。
4Traversal 3访问 D 并将其标记为已访问并放入堆栈。这里,我们有 BC 节点,它们与 D 相邻,并且都未被访问过。但是,我们还是要按照字母顺序进行选择。
5Traversal 4我们选择 B,将其标记为已访问并放入堆栈。这里 B 没有任何未访问的相邻节点。因此,我们从堆栈中弹出 B
6Traversal 5我们检查堆栈顶部是否返回到前一个节点,并检查它是否有任何未访问的节点。在这里,我们发现 D 位于堆栈顶部。
7Traversal 6现在只有来自 D 的未访问相邻节点是 C。所以我们访问 C,将其标记为已访问并将其放入堆栈。

由于 C 没有任何未访问的相邻节点,因此我们不断弹出堆栈,直到找到具有未访问相邻节点的节点。在这种情况下,没有未访问的相邻节点,我们继续弹出直到堆栈为空。让我们看看如何在 JavaScript 中实现这一点。

示例

DFS(node) {
   // 创建一个 Stack 并在其中添加我们的初始节点
   let s = new Stack(this.nodes.length);
   let explored = new Set();
   s.push(node);

   // 将第一个节点标记为已探索
   explored.add(node);

   // 我们将继续,直到 Stack 变空
   while (!s.isEmpty()) {
      let t = s.pop();

   // 记录从 Stack 中出来的每个元素
      console.log(t);

   // 1. 在边对象中,我们搜索此节点直接连接到的节点。
   // 2. 我们过滤掉已经被探索过的节点。
   // 3. 然后我们将每个未探索的节点标记为已探索并将其推送到堆栈。
   this.edges[t]
   .filter(n => !explored.has(n))
   .forEach(n => {
      explored.add(n);
      s.push(n);
      });
   }
}

嗯,这很简单。我们实际上只是将队列换成了堆栈,然后我们就有了 DFS。这实际上是两者之间的唯一区别。DFS 也可以使用递归来实现。但在这种情况下最好避免这种情况,因为更大的图意味着我们需要额外的内存来跟踪调用堆栈。

您可以使用以下方法进行测试 −

let g = new Graph();
g.addNode("A");
g.addNode("B");
g.addNode("C");
g.addNode("D");
g.addNode("E");
g.addNode("F");
g.addNode("G");

g.addEdge("A", "C");
g.addEdge("A", "B");
g.addEdge("A", "D");
g.addEdge("D", "E");
g.addEdge("E", "F");
g.addEdge("B", "G");

g.DFS("A");

输出

This will give the output.

A
D
E
F
B
G
C

相关文章