返回

深度优先搜索( DFS)和广度优先搜索( BDS)详解

后端




深度优先搜索( DFS)和广度优先搜索( BDS)详解

广度优先搜索( BDS)

1.1 前言

和树的遍历 مشابه,图的遍历也是从图中某点出发,然后用某种方法对图中所有顶点进行访问,且仅访问一次。

但是图的遍历又和树的遍历不同,主要的不同点在于:

  • 图中可能存在回路,所以可能出现访问某个顶点多次的情况。
  • 图中可能存在多条到达同一顶点的路径,所以需要进行遍历图中所有的边,才能把所有到达该顶点的路径都找出来。

1.2 思路

广度优先搜索的思路很直观:从一个结点出发,访问它相连接的结点,然后访问相连接结点的相连接的结点,...,直到访问所有结点。

广度优先搜索用一个队列来实现。将起始结点放入队首,然后依次将结点的相连接的结点放入队尾。当队列不空时,从队首取出一个结点并访问它。

1.3 实现

# 图的定义
class Graph:
    def __init__(self):
        self.nodes = {}

    def add_node(self, node):
        self.nodes[node] = set()

    def add_edge(self, node1, node2):
        self.nodes[node1].add(node2)
        self.nodes[node2].add(node1)

# 广度优先搜索
def bfs(graph, start_node):
    # 初始化队列和访问标记
    queue = [start_node]
    visited = set()
    visited.add(start_node)

    # 从队列中取出结点并访问之
    while queue:
        node = queue.pop()
        yield node

        # 将结点的相连接结点放入队尾
        for next_node in graph.nodes[node]:
            if next_node not in visited:
                queue.append(next_node)
                visited.add(next_node)

# 使用
graph = Graph()
graph.add_node('A')
graph.add_node('B')
graph.add_node('C')
graph.add_edge('A', 'B')
graph.add_edge('B', 'C')

for node in bfs(graph, 'A'):
    print(node)

深度优先搜索( DFS)

2.1 前言

深度优先搜索的思路也比较直观:从一个结点出发,访问它相连接的结点,然后访问相连接结点的相连接的结点,...,直到访问到最深层的结点。

深度优先搜索用一个堆叠来实现。将起始结点压入堆叠,然后依次将结点的相连接的结点压入堆叠。当堆叠不空时,从堆叠中弹出一个结点并访问它。

2.2 实现

# 图的定义
class Graph:
    def __init__(self):
        self.nodes = {}

    def add_node(self, node):
        self.nodes[node] = set()

    def add_edge(self, node1, node2):
        self.nodes[node1].add(node2)
        self.nodes[node2].add(node1)

# 广度优先搜索
def bfs(graph, start_node):
    # 初始化堆叠和访问标记
    stack = [start_node]
    visited = set()
    visited.add(start_node)

    # 从堆叠中取出结点并访问之
    while stack:
        node = stack.pop()
        yield node

        # 将结点的相连接结点压入堆叠
        for next_node in graph.nodes[node]:
            if next_node not in visited:
                stack.append(next_node)
                visited.add(next_node)

# 使用
graph = Graph()
graph.add_node('A')
graph.add_node('B')
graph.add_node('C')
graph.add_edge('A', 'B')
graph.add_edge('B', 'C')

for node in bfs(graph, 'A'):
    print(node)

3 比较

广度优先搜索和深度优先搜索的区别在于,广度优先搜索更注重广度优先,即更倾向于访问结点的相连接结点;而深度优先搜索更注重深度优先,即更倾向于访问结点的最深层的结点。

广度优先搜索适用于求最短路径、最少跳数、最小生成树等问题;深度优先搜索适用于求联通分支、割点、桥、强连通分量等问题。