图论:图的遍历(DFS vs. BFS)

引言

图的遍历是图论中的核心概念,通过不同的遍历方法能够有效地处理多种问题,例如连通性检测、路径查找、图的最小生成树等。本篇我们将重点探讨图的深度优先搜索(DFS)和广度优先搜索(BFS)两种常见的图遍历方法,分析它们的原理、应用场景以及实现方法,并通过实际案例代码分析问题解决方案。

在这里插入图片描述

基本概念

图是一种表示对象间关系的数据结构,由顶点和边组成。按照边的方向,图可以分为有向图和无向图。图的遍历主要有两种方式:

  • 深度优先搜索(DFS):优先深入图的分支,直到无法继续时回溯。
  • 广度优先搜索(BFS):优先探索与当前节点相邻的节点,然后逐层向外扩展。

无向图示例

下面是一个无向图示例,适合用于探讨图的遍历(深度优先搜索和广度优先搜索)。

    A
   / \
  B  C
 /|  |
D |  |
 \|  |
  E--F
  |  |
  G  H
   \ |
    I

在这个图中,节点的连接关系如下:

  • A 连接 B、C
  • B 连接 D、E
  • C 连接 E、F
  • D 连接 E
  • E 连接 G、F
  • F 连接 H
  • G 连接 I
  • H 连接 I

绘制图形

下面的代码使用 networkxmatplotlib 库绘制该图。请确保已安装这两个库(如果尚未安装,请运行 pip install networkx matplotlib)。

以下是绘制上述无向图的 Python 代码:

import matplotlib.pyplot as plt
import networkx as nx

# 创建空图
G = nx.Graph()

# 添加节点和边
edges = [
    ('A', 'B'),
    ('A', 'C'),
    ('B', 'D'),
    ('B', 'E'),
    ('C', 'E'),
    ('C', 'F'),
    ('D', 'E'),
    ('E', 'F'),
    ('E', 'G'),
    ('F', 'H'),
    ('G', 'I'),
    ('H', 'I')
]

G.add_edges_from(edges)

# 绘制图形
pos = nx.spring_layout(G)  # 选择布局
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=700, font_size=12, font_weight='bold', edge_color='gray')

# 显示图形
plt.title("无向图示例")
plt.show()

运行上述代码将生成一个表示上述无向图的可视化图形,为后续对深度优先搜索(DFS)和广度优先搜索(BFS)的探讨提供一个演示基础。

在这里插入图片描述

代码释意

  • 导入库:使用 matplotlib.pyplot 来绘制图形,使用 networkx 来处理图结构。
  • 创建图:创建一个无向图对象 G
  • 添加边:通过 add_edges_from 方法将边添加到图中,定义节点之间的连接关系。
  • 设置图的布局:使用 spring_layout 选择图形的布局,这有助于更清晰地展示图的结构。
  • 绘制图形:使用 nx.draw 来绘制图,设置节点的颜色、大小和标签。
  • 显示图:通过 plt.show() 来显示绘制的图形。

深度优先搜索(DFS)

基本概念

深度优先搜索利用栈(可以用递归实现)来访问图中的节点。当访问一个节点时,会深度探索该节点的所有相邻节点,直到无法继续。

算法步骤

  1. 从起始节点开始,标记为已访问。
  2. 递归访问未访问的相邻节点。
  3. 如果所有相邻节点都已访问,回溯到上一个节点。

下面我们将逐步展示如何使用 Python 代码演示无向图的深度优先搜索(DFS)过程与效果吗,并实现 DFS 算法。

可视化 DFS 过程

在实现 DFS 并打印结果后,我们可以通过 matplotlib 绘制这幅图以可视化 DFS 的遍历过程。为了展示仍然在访问中的节点,我们将在访问每个节点时更新图像。

以下是完整的 DFS 过程可视化实现:

import matplotlib.pyplot as plt
import networkx as nx
import time

class Graph:
    def __init__(self):
        self.graph = nx.Graph()  # 使用 networkx 的 Graph 对象

    def add_edge(self, u, v):
        self.graph.add_edge(u, v)  # 直接添加边到 Graph 对象

    def dfs(self, start):
        visited = set()
        path = []
        self._dfs_util(start, visited, path)
        return path

    def _dfs_util(self, vertex, visited, path):
        visited.add(vertex)
        path.append(vertex)  # 记录路径
        self.visualize_dfs(path)  # 可视化图遍历
        for neighbor in self.graph[vertex]:  # 使用 networkx 的方式访问相邻节点
            if neighbor not in visited:
                self._dfs_util(neighbor, visited, path)

    def visualize_dfs(self, path):
        plt.clf()  # 清空当前的图
        pos = nx.spring_layout(self.graph)
        nx.draw(self.graph, pos, with_labels=True, node_color='lightblue', node_size=700, font_size=12, font_weight='bold'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三余知行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值