图是数据结构中一种重要的非线性结构,用于表示对象之间的多对多关系

图是数据结构中一种重要的非线性结构,用于表示对象之间的多对多关系。以下是对你提供内容的系统化梳理与补充说明:


一、图的核心概念

1. 连通图与连通分量
  • 连通图:在无向图中,若任意两个顶点之间都存在路径,则称该图为连通图
  • 连通分量:无向图中的极大连通子图称为连通分量。
    • “极大”意味着不能再加入更多顶点和边而保持连通性。
    • 对于非连通图,它有多个连通分量。

✅ 示例:一个由三个互不相连的三角形组成的无向图,共有3个连通分量。

2. 强连通图与强连通分量
  • 强连通图:在有向图中,若任意两顶点 viv_ivivjv_jvj 之间都互相可达(即存在 vi→vjv_i \to v_jvivjvj→viv_j \to v_ivjvi 的路径),则称为强连通图。
  • 强连通分量:有向图中的极大连通子图,其中每对顶点都互相可达。
    • 注意:不是所有有向图都是强连通的,但每个顶点本身至少属于一个强连通分量。

🔍 应用:Kosaraju算法、Tarjan算法可用于求解有向图的强连通分量。

3. 网(网络图)
  • 指边或弧上带有权值的图,通常表示距离、成本、时间等。
  • 权可以为正数、负数(需注意负权环)、零。
  • 常见于最短路径问题(如Dijkstra、Floyd-Warshall)和最小生成树(如Prim、Kruskal)。
4. 有向树
  • 一种特殊的有向图:
    • 恰有一个顶点入度为0(称为根节点);
    • 其余顶点入度均为1;
    • 忽略方向后形成一棵树。
  • 特点:从根出发可到达所有其他节点,且无环。

📌 应用:常用于表示组织结构、文件系统、语法树等层次结构。


二、图的存储结构 —— 邻接矩阵表示法

基本定义
  • 使用一个 n×nn \times nn×n 的二维数组 A 表示具有 nnn 个顶点的图。
  • 元素定义如下:
    A[i][j]={1若 (vi,vj) 或 ⟨vi,vj⟩ 是边0否则 A[i][j] = \begin{cases} 1 & \text{若 } (v_i, v_j) \text{ 或 } \langle v_i, v_j \rangle \text{ 是边} \\ 0 & \text{否则} \end{cases} A[i][j]={10 (vi,vj)  vi,vj 是边否则
特性分析
图类型邻接矩阵性质度的计算方式
无向图对称矩阵(A[i][j]=A[j][i]A[i][j] = A[j][i]A[i][j]=A[j][i]顶点 viv_ivi 的度 = 第 iii 行(或列)中非0元素个数
有向图不一定对称出度 = 第 iii 行非0个数;入度 = 第 iii 列非0个数
网的邻接矩阵

对于带权图(网),邻接矩阵定义为:
A[i][j]={Wij若存在边 (vi,vj)∞否则(或用特殊值如 -1、INF 表示无穷大) A[i][j] = \begin{cases} W_{ij} & \text{若存在边 } (v_i, v_j) \\ \infty & \text{否则(或用特殊值如 -1、INF 表示无穷大)} \end{cases} A[i][j]={Wij若存在边 (vi,vj)否则(或用特殊值如 -1INF 表示无穷大)

  • 实现时常用 float('inf') 或一个极大值代替 ∞\infty
  • 主对角线一般设为 0(自身到自身的距离为0)。
优缺点总结
优点缺点
边的存在性查询快(O(1)O(1)O(1)空间复杂度高:O(n2)O(n^2)O(n2),稀疏图浪费严重
易实现图算法(如Floyd)插入/删除顶点代价高(需重新分配矩阵)
支持快速计算度、路径判断不适合顶点数极多但边很少的情况(稀疏图)

适用场景建议

  • 顶点数量较少且图较稠密时,优先使用邻接矩阵;
  • 若图稀疏,推荐使用邻接表以节省空间。

判断一个有向图是否为强连通图,可以基于邻接矩阵使用以下方法:


✅ 方法:利用深度优先搜索(DFS)或可达性矩阵

由于邻接矩阵本身只表示直接边的关系,要判断强连通性,需要知道任意两个顶点之间是否互相可达。具体步骤如下:


🔧 步骤一:从任一顶点出发进行 DFS(基于邻接矩阵)

  1. 选择任意一个顶点 v0v_0v0
  2. 使用邻接矩阵实现 DFS,记录能访问到的所有顶点;
  3. 如果不能访问所有 nnn 个顶点 → 不是强连通图。

🔧 步骤二:将邻接矩阵转置(即边反向),再做一次 DFS

  • 转置矩阵 ATA^TAT 表示原图中所有边的方向反转;
  • 在转置图上从同一个顶点 v0v_0v0 开始 DFS;
  • 若仍不能访问全部顶点 → 也不是强连通图。

💡 原理:若在原图和反图中都能从 v0v_0v0 到达所有其他点,则说明任意两点间双向可达。


✅ 判定条件:

只有当 原图的 DFS 访问了所有顶点,且 反图的 DFS 也访问了所有顶点 时,该有向图才是强连通图


🧮 示例代码(Python 风格伪代码)

def is_strongly_connected(adj_matrix):
    n = len(adj_matrix)
    
    def dfs(start, graph):
        visited = [False] * n
        stack = [start]
        while stack:
            u = stack.pop()
            if not visited[u]:
                visited[u] = True
                for v in range(n):
                    if graph[u][v] and not visited[v]:
                        stack.append(v)
        return visited

    # 第一步:原图 DFS
    visited1 = dfs(0, adj_matrix)
    if not all(visited1):
        return False

    # 第二步:转置图 DFS(边反向)
    transpose = [[adj_matrix[j][i] for j in range(n)] for i in range(n)]
    visited2 = dfs(0, transpose)
    if not all(visited2):
        return False

    return True

⏱️ 时间复杂度

  • 每次 DFS:O(n2)O(n^2)O(n2)(因为遍历整个矩阵的行);
  • 总时间复杂度:O(n2)O(n^2)O(n2)
  • 空间复杂度:O(n)O(n)O(n)(用于 visited 数组和栈)。

补充说明

  • 对于更大的图或频繁查询,可构造可达性矩阵(如用 Floyd-Warshall 算法传递闭包),然后检查是否所有点对 (i,j)(i,j)(i,j)(j,i)(j,i)(j,i) 均可达。
  • Floyd-Warshall 后判断:对所有 i,ji,ji,j,都有 reach[i][j] == Truereach[j][i] == True

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Bol5261

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

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

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

打赏作者

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

抵扣说明:

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

余额充值