数据结构:邻接矩阵

邻接矩阵

资料:https://pan.quark.cn/s/43d906ddfa1bhttps://pan.quark.cn/s/90ad8fba8347https://pan.quark.cn/s/d9d72152d3cf

一、邻接矩阵的定义

邻接矩阵是 的一种基础存储方式,通过一个二维数组 来表示图中顶点之间的邻接关系。对于包含 n 个顶点的图,邻接矩阵是一个 n×n 的矩阵 adj,矩阵中的元素 adj[i][j] 用于标识顶点 i 和顶点 j 之间是否存在边,以及边的相关属性(如权重)。

邻接矩阵可同时存储无向图、有向图和加权图,仅需调整矩阵元素的取值规则。

二、邻接矩阵的取值规则

1. 无权无向图

  • 若顶点 i 和顶点 j 之间存在无向边,则 adj[i][j] = 1adj[j][i] = 1(矩阵对称);
  • 若不存在边,则 adj[i][j] = 0adj[j][i] = 0
  • 顶点自身无环时,adj[i][i] = 0(允许自环的场景可设为1)。

2. 无权有向图

  • 若存在从顶点 i 指向顶点 j 的有向边,则 adj[i][j] = 1
  • 若不存在该方向的边,则 adj[i][j] = 0
  • 矩阵非对称adj[i][j]adj[j][i] 无必然相等关系)。

3. 加权图

  • 若顶点 ij 存在边且权重为 w,则 adj[i][j] = w
  • 若不存在边,则 adj[i][j] = ∞(通常用一个极大值表示,如 float('inf'));
  • 无向加权图的矩阵对称,有向加权图的矩阵非对称。

三、邻接矩阵的核心特性

  1. 对称性

    • 无向图的邻接矩阵是对称矩阵 ,即 adj[i][j] = adj[j][i]
    • 有向图的邻接矩阵通常非对称,仅在两顶点间存在双向边时对应位置元素相等。
  2. 空间复杂度

    • 固定为 O(n²),其中 n 为顶点数量,与图的边数无关;
    • 对于稀疏图(边数远小于 ),会造成大量空间浪费;对于稠密图(边数接近 ),空间利用率较高。
  3. 操作效率

    • 查询边是否存在 :时间复杂度为 O(1),可直接通过矩阵下标访问;
    • 查询顶点的度
      • 无向图中,顶点 i 的度为第 i 行(或第 i 列)所有元素的和;
      • 有向图中,顶点 i 的出度为第 i 行元素和,入度为第 i 列元素和;
    • 添加/删除边 :时间复杂度为 O(1),仅需修改对应矩阵元素的值;
    • 遍历顶点邻接边 :时间复杂度为 O(n),需遍历该行所有 n 个元素,效率低于邻接表。

四、邻接矩阵的实现示例

1. 无权无向图的邻接矩阵实现

python 复制代码
class AdjMatrixUndirectedGraph:
    def __init__(self, num_vertices):
        self.num_vertices = num_vertices
        # 初始化n×n的零矩阵
        self.adj_matrix = [[0 for _ in range(num_vertices)] for _ in range(num_vertices)]
    
    def add_edge(self, u, v):
        """添加无向边(u, v)"""
        if 0 <= u < self.num_vertices and 0 <= v < self.num_vertices:
            self.adj_matrix[u][v] = 1
            self.adj_matrix[v][u] = 1
    
    def remove_edge(self, u, v):
        """删除无向边(u, v)"""
        if 0 <= u < self.num_vertices and 0 <= v < self.num_vertices:
            self.adj_matrix[u][v] = 0
            self.adj_matrix[v][u] = 0
    
    def has_edge(self, u, v):
        """判断是否存在边(u, v)"""
        if 0 <= u < self.num_vertices and 0 <= v < self.num_vertices:
            return self.adj_matrix[u][v] == 1
        return False
    
    def get_vertex_degree(self, v):
        """获取顶点v的度"""
        if 0 <= v < self.num_vertices:
            return sum(self.adj_matrix[v])
        return -1
    
    def dfs(self, start, visited=None):
        """深度优先搜索(基于邻接矩阵)"""
        if visited is None:
            visited = [False] * self.num_vertices
        visited[start] = True
        print(start, end=" ")
        for i in range(self.num_vertices):
            if self.adj_matrix[start][i] == 1 and not visited[i]:
                self.dfs(i, visited)

2. 加权有向图的邻接矩阵实现

python 复制代码
class AdjMatrixWeightedDigraph:
    def __init__(self, num_vertices):
        self.num_vertices = num_vertices
        INF = float('inf')
        # 初始化n×n矩阵,默认无无边(权重为无穷大),自身到自身权重为0
        self.adj_matrix = [[INF for _ in range(num_vertices)] for _ in range(num_vertices)]
        for i in range(num_vertices):
            self.adj_matrix[i][i] = 0
    
    def add_edge(self, u, v, weight):
        """添加有向边<u, v>,权重为weight"""
        if 0 <= u < self.num_vertices and 0 <= v < self.num_vertices:
            self.adj_matrix[u][v] = weight
    
    def get_edge_weight(self, u, v):
        """获取边<u, v>的权重"""
        if 0 <= u < self.num_vertices and 0 <= v < self.num_vertices:
            return self.adj_matrix[u][v]
        return float('inf')
    
    def floyd_warshall(self):
        """Floyd-Warshall算法求解多源最短路径"""
        n = self.num_vertices
        # 初始化距离矩阵为邻接矩阵
        dist = [row[:] for row in self.adj_matrix]
        
        # 遍历中间顶点k
        for k in range(n):
            # 遍历起点i
            for i in range(n):
                # 遍历终点j
                for j in range(n):
                    # 通过中间顶点k优化i到j的路径
                    if dist[i][k] + dist[k][j] < dist[i][j]:
                        dist[i][j] = dist[i][k] + dist[k][j]
        
        return dist

使用示例

python 复制代码
# 无权无向图示例
undir_graph = AdjMatrixUndirectedGraph(5)
undir_graph.add_edge(0, 1)
undir_graph.add_edge(0, 2)
undir_graph.add_edge(1, 3)
print("顶点0的度:", undir_graph.get_vertex_degree(0))  # 输出2
print("是否存在边(0,1):", undir_graph.has_edge(0,1))  # 输出True
print("DFS遍历结果:")
undir_graph.dfs(0)  # 输出0 1 3 2

# 加权有向图示例
weighted_digraph = AdjMatrixWeightedDigraph(4)
weighted_digraph.add_edge(0, 1, 2)
weighted_digraph.add_edge(0, 2, 4)
weighted_digraph.add_edge(1, 2, 1)
weighted_digraph.add_edge(1, 3, 7)
weighted_digraph.add_edge(2, 3, 3)
shortest_dist = weighted_digraph.floyd_warshall()
print("\n多源最短路径矩阵:")
for row in shortest_dist:
    print(row)

五、邻接矩阵与邻接表的对比

特性 邻接矩阵 邻接表
空间复杂度 O(n²),与边数无关 O(
边存在性查询 O(1),效率高 O(deg(v)),需遍历邻接表
邻接边遍历 O(n),需遍历整行 O(deg(v)),仅遍历邻接顶点
边添加/删除 O(1),直接修改元素 链表/数组操作,效率视结构而定
适用场景 稠密图、顶点数少的图 稀疏图、顶点数多的图

六、邻接矩阵的典型应用

  1. 稠密图的存储与操作:如完全图、社交网络中高连通度的子图,邻接矩阵的空间利用率高且查询效率优;
  2. 多源最短路径求解:Floyd-Warshall算法基于邻接矩阵实现,可高效求解任意两顶点间的最短路径;
  3. 图的连通性快速判断:通过矩阵幂运算(邻接矩阵的k次幂可表示k步可达性),判断顶点间的路径存在性;
  4. 小规模图的可视化:邻接矩阵的二维结构可直观展示顶点间的连接关系,便于人工分析。
相关推荐
额呃呃1 天前
二分查找细节理解
数据结构·算法
无尽的罚坐人生1 天前
hot 100 283. 移动零
数据结构·算法·双指针
蜂蜜黄油呀土豆1 天前
Redis 底层实现深度解析:从 ListPack 到哈希表扩容
数据结构·redis·zset·sds·listpack·哈希表扩容
郝学胜-神的一滴1 天前
Linux进程与线程控制原语对比:双刃出鞘,各显锋芒
linux·服务器·开发语言·数据结构·c++·程序人生
javachen__1 天前
341-十道经典程序设计题目
数据结构·c++·算法
毅炼1 天前
hot100打卡——day08
java·数据结构·算法·leetcode·深度优先
denggun123451 天前
悬垂指针 和 野指针
数据结构
Pluto_CSND1 天前
JSONPath解析JSON数据结构
java·数据结构·json
无限进步_1 天前
【C语言】用队列实现栈:数据结构转换的巧妙设计
c语言·开发语言·数据结构·c++·链表·visual studio
liu****1 天前
02_Pandas_数据结构
数据结构·python·pandas·python基础