返回
深度优先搜索( DFS)和广度优先搜索( BDS)详解
后端
2024-01-09 18:33:19
深度优先搜索( 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 比较
广度优先搜索和深度优先搜索的区别在于,广度优先搜索更注重广度优先,即更倾向于访问结点的相连接结点;而深度优先搜索更注重深度优先,即更倾向于访问结点的最深层的结点。
广度优先搜索适用于求最短路径、最少跳数、最小生成树等问题;深度优先搜索适用于求联通分支、割点、桥、强连通分量等问题。