当前位置: 首页 > news >正文

Python数据结构高级:图的表示与遍历

Python数据结构高级:图的表示与遍历

一、图的基本概念

1.1 图的定义与分类

图(Graph)是由顶点(Vertex)集合和边(Edge)集合组成的数据结构,形式化表示为 G = (V, E)

主要分类:

  • 无向图 vs 有向图
    # 无向图示例:A-B-C
    # 有向图示例:A→B→C
    
  • 权重图 vs 非权重图
    # 权重图示例:A-(5)-B-(3)-C
    # 非权重图示例:A-B-C
    

1.2 典型应用场景

  • 社交网络:用户为顶点,关注关系为边
  • 交通网络:城市为顶点,路线为带权边
  • 知识图谱:实体为顶点,关系为边
  • 推荐系统:用户-商品交互关系建模

二、图的表示方法

2.1 邻接矩阵

使用二维数组表示顶点间的连接关系

class AdjMatrixGraph:
    def __init__(self, vertices):
        self.size = len(vertices)
        self.vertices = vertices
        self.matrix = [[0]*self.size for _ in range(self.size)]
        self.index_map = {v:i for i,v in enumerate(vertices)}

    def add_edge(self, u, v, weight=1):
        i = self.index_map[u]
        j = self.index_map[v]
        self.matrix[i][j] = weight
        # 若是无向图需添加反向
        # self.matrix[j][i] = weight

时间复杂度分析:

  • 查询相邻节点:O(1)
  • 遍历所有边:O(V²)
  • 空间复杂度:O(V²)

2.2 邻接表

使用字典+链表存储连接关系(更节省空间)

from collections import defaultdict

class Graph:
    def __init__(self):
        self.adj_list = defaultdict(list)
    
    def add_edge(self, u, v, weight=None):
        self.adj_list[u].append((v, weight))
        # 若是无向图需添加反向
        # self.adj_list[v].append((u, weight))

时间复杂度分析:

  • 查询相邻节点:O(1)平均
  • 遍历所有边:O(V+E)
  • 空间复杂度:O(V+E)

三、图的遍历算法

3.1 深度优先搜索(DFS)

def dfs(graph, start):
    visited = set()
    stack = [start]
    
    while stack:
        vertex = stack.pop()
        if vertex not in visited:
            print(vertex, end=' ')
            visited.add(vertex)
            # 逆序压栈保证顺序一致性
            for neighbor in reversed(graph.adj_list[vertex]):
                if neighbor[0] not in visited:
                    stack.append(neighbor[0])

应用场景:

  • 拓扑排序
  • 检测环路
  • 寻找连通分量

3.2 广度优先搜索(BFS)

from collections import deque

def bfs(graph, start):
    visited = set()
    queue = deque([start])
    
    while queue:
        vertex = queue.popleft()
        if vertex not in visited:
            print(vertex, end=' ')
            visited.add(vertex)
            for neighbor in graph.adj_list[vertex]:
                if neighbor[0] not in visited:
                    queue.append(neighbor[0])

应用场景:

  • 最短路径查找(未加权图)
  • 社交网络的好友推荐
  • 网页爬虫的URL遍历

四、完整代码示例

class Graph:
    def __init__(self):
        self.adj_list = defaultdict(list)
    
    def add_edge(self, u, v, weight=None):
        self.adj_list[u].append((v, weight))
    
    def dfs(self, start):
        visited = set()
        self._dfs_recursive(start, visited)
    
    def _dfs_recursive(self, vertex, visited):
        if vertex not in visited:
            print(vertex, end=' ')
            visited.add(vertex)
            for neighbor in self.adj_list[vertex]:
                self._dfs_recursive(neighbor[0], visited)
    
    def bfs(self, start):
        visited = set()
        queue = deque([start])
        
        while queue:
            vertex = queue.popleft()
            if vertex not in visited:
                print(vertex, end=' ')
                visited.add(vertex)
                for neighbor in self.adj_list[vertex]:
                    if neighbor[0] not in visited:
                        queue.append(neighbor[0])

# 使用示例
if __name__ == "__main__":
    g = Graph()
    g.add_edge('A', 'B')
    g.add_edge('A', 'C')
    g.add_edge('B', 'D')
    g.add_edge('C', 'E')
    g.add_edge('D', 'E')
    
    print("DFS遍历结果:")
    g.dfs('A')  # 输出:A B D E C 
    
    print("\nBFS遍历结果:")
    g.bfs('A')  # 输出:A B C D E 

五、每日挑战:路径存在性判断

def has_path(graph, start, end):
    visited = set()
    stack = [start]
    
    while stack:
        current = stack.pop()
        if current == end:
            return True
        if current not in visited:
            visited.add(current)
            for neighbor in graph.adj_list[current]:
                if neighbor[0] not in visited:
                    stack.append(neighbor[0])
    return False

# 测试用例
g = Graph()
g.add_edge('A', 'B')
g.add_edge('B', 'C')
g.add_edge('C', 'D')

print(has_path(g, 'A', 'D'))  # 输出:True
print(has_path(g, 'D', 'A'))  # 输出:False

算法选择建议:

  • 最短路径问题 → BFS
  • 拓扑排序 → DFS
  • 存在性判断 → 两者均可

六、扩展应用

  1. 加权图的最短路径(Dijkstra算法)
  2. 最小生成树(Prim/Kruskal算法)
  3. 社交网络分析(使用NetworkX库)
  4. 图数据库应用(Neo4j的Python接口)
# Dijkstra算法示例
import heapq

def dijkstra(graph, start):
    distances = {vertex: float('inf') for vertex in graph}
    distances[start] = 0
    heap = [(0, start)]
    
    while heap:
        current_dist, current_vertex = heapq.heappop(heap)
        
        if current_dist > distances[current_vertex]:
            continue
            
        for neighbor, weight in graph[current_vertex]:
            distance = current_dist + weight
            if distance < distances[neighbor]:
                distances[neighbor] = distance
                heapq.heappush(heap, (distance, neighbor))
    
    return distances

学习建议:

  1. 使用可视化工具(如Graphviz)辅助理解
  2. 在LeetCode上练习相关题目(如207.课程表、133.克隆图)
  3. 阅读NetworkX库源码学习工业级实现
  4. 尝试实现A*算法等高级图算法

掌握图的表示与遍历是理解复杂算法的基础,后续可继续学习强连通分量、最大流等高级主题。

相关文章:

  • 验证码介绍及生成与验证
  • 去耦电容的作用详解
  • 网络安全之Web后端Python
  • v4l2子系统学习(五)subdev和media子系统
  • git 命令 设置别名
  • QT 引入Quazip和Zlib源码工程到项目中,无需编译成库,跨平台,加密压缩,带有压缩进度
  • Django数据库操作
  • 深入探究 C 语言内存函数:memcpy、memmove、memset 和 memcmp
  • VMware17.6+CentOS 8安装教程
  • 比较Spring AOP和AspectJ
  • [晕事]今天做了件晕事65,gcc,cmake, pragam
  • NGINX配置TCP负载均衡
  • Go基础之环境搭建
  • 【前端开发】能不能用Vue+Bootstrap进行项目开发?有什么需求场景需要用到的地方
  • 基于YOLO11深度学习的苹果叶片病害检测识别系统【python源码+Pyqt5界面+数据集+训练代码】
  • 硬件工程师入门教程
  • IDE(集成开发环境)
  • Flutter 实现抖音风格底部导航栏
  • PING命令TTL解析
  • LangChain大模型应用开发:基于RAG实现文档问答
  • 地方网站怎么做/关键词排名优化怎么做
  • wordpress app 管理/南宁seo产品优化服务
  • 制作表情包的软件/seo点击
  • 网站标题是关键词吗/免费找精准客户的app
  • 哪些公司做网站好/优化大师专业版
  • 莱芜新闻综合频道/搜索关键词优化排名