news 2026/10/8 12:24:42

图算法:从基础到应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
图算法:从基础到应用

一、引言
图是一种强大的数据结构,用于表示对象之间的关系。从社交网络到路线规划,从网页连接到生物信息学,图算法在计算机科学的各个领域都有着广泛的应用。本文将介绍图的基本概念、常见算法及其实现。

二、图的表示方法

  1. 邻接矩阵
classGraphMatrix:def__init__(self,vertices):self.V=vertices self.graph=[[0]*verticesfor_inrange(vertices)]defadd_edge(self,u,v,weight=1,directed=False):self.graph[u][v]=weightifnotdirected:self.graph[v][u]=weightdefprint_graph(self):foriinrange(self.V):print(f"顶点{i}:{self.graph[i]}")
  1. 邻接表(更节省空间)
fromcollectionsimportdefaultdictclassGraphAdjList:def__init__(self,directed=False):self.graph=defaultdict(list)self.directed=directed self.vertices=set()defadd_edge(self,u,v,weight=1):self.graph[u].append((v,weight))self.vertices.add(u)self.vertices.add(v)ifnotself.directed:self.graph[v].append((u,weight))defprint_graph(self):forvertexinself.graph:print(f"{vertex}:{self.graph[vertex]}")

三、基础图遍历算法

  1. 深度优先搜索 (DFS)
defdfs_recursive(graph,start,visited=None):"""递归实现DFS"""ifvisitedisNone:visited=set()visited.add(start)print(start,end=" ")forneighbor,_ingraph.get(start,[]):ifneighbornotinvisited:dfs_recursive(graph,neighbor,visited)returnvisiteddefdfs_iterative(graph,start):"""迭代实现DFS"""visited=set()stack=[start]whilestack:vertex=stack.pop()ifvertexnotinvisited:print(vertex,end=" ")visited.add(vertex)# 将邻居逆序加入栈中,以保持与递归相同的遍历顺序forneighbor,_inreversed(graph.get(vertex,[])):ifneighbornotinvisited:stack.append(neighbor)returnvisited
  1. 广度优先搜索 (BFS)
fromcollectionsimportdequedefbfs(graph,start):"""BFS实现"""visited=set([start])queue=deque([start])whilequeue:vertex=queue.popleft()print(vertex,end=" ")forneighbor,_ingraph.get(vertex,[]):ifneighbornotinvisited:visited.add(neighbor)queue.append(neighbor)returnvisited

四、最短路径算法

  1. Dijkstra算法(单源最短路径,权重非负)
importheapqdefdijkstra(graph,start):"""Dijkstra最短路径算法"""# 初始化距离字典distances={vertex:float('inf')forvertexingraph}distances[start]=0previous={vertex:Noneforvertexingraph}# 优先队列priority_queue=[(0,start)]whilepriority_queue:current_distance,current_vertex=heapq.heappop(priority_queue)# 如果当前距离大于已知最短距离,跳过ifcurrent_distance>distances[current_vertex]:continue# 更新邻居节点的距离forneighbor,weightingraph.get(current_vertex,[]):distance=current_distance+weightifdistance<distances[neighbor]:distances[neighbor]=distance previous[neighbor]=current_vertex heapq.heappush(priority_queue,(distance,neighbor))returndistances,previousdefget_path(previous,target):"""从previous字典重构路径"""path=[]current=targetwhilecurrentisnotNone:path.append(current)current=previous[current]returnpath[::-1]
  1. Floyd-Warshall算法(所有节点对最短路径)
deffloyd_warshall(graph_matrix,vertices):"""Floyd-Warshall算法"""# 初始化距离矩阵dist=[[float('inf')]*verticesfor_inrange(vertices)]foriinrange(vertices):dist[i][i]=0forj,weightinenumerate(graph_matrix[i]):ifweight!=0:dist[i][j]=weight# 动态规划forkinrange(vertices):foriinrange(vertices):forjinrange(vertices):ifdist[i][j]>dist[i][k]+dist[k][j]:dist[i][j]=dist[i][k]+dist[k][j]returndist

五、最小生成树算法

  1. Prim算法
defprim_mst(graph,start):"""Prim最小生成树算法"""mst=[]visited=set([start])edges=[]# 初始化起始点的边forneighbor,weightingraph.get(start,[]):heapq.heappush(edges,(weight,start,neighbor))whileedgesandlen(visited)<len(graph):weight,u,v=heapq.heappop(edges)ifvnotinvisited:visited.add(v)mst.append((u,v,weight))# 添加新顶点的边forneighbor,wingraph.get(v,[]):ifneighbornotinvisited:heapq.heappush(edges,(w,v,neighbor))returnmst
  1. Kruskal算法
classDisjointSet:"""并查集实现,用于Kruskal算法"""def__init__(self,vertices):self.parent={v:vforvinvertices}self.rank={v:0forvinvertices}deffind(self,v):ifself.parent[v]!=v:self.parent[v]=self.find(self.parent[v])returnself.parent[v]defunion(self,v1,v2):root1=self.find(v1)root2=self.find(v2)ifroot1!=root2:ifself.rank[root1]>self.rank[root2]:self.parent[root2]=root1elifself.rank[root1]<self.rank[root2]:self.parent[root1]=root2else:self.parent[root2]=root1 self.rank[root1]+=1returnTruereturnFalsedefkruskal_mst(graph):"""Kruskal最小生成树算法"""edges=[]vertices=set()# 收集所有边foruingraph:vertices.add(u)forv,weightingraph.get(u,[]):vertices.add(v)edges.append((weight,u,v))# 按权重排序edges.sort()# 初始化并查集ds=DisjointSet(vertices)mst=[]forweight,u,vinedges:ifds.union(u,v):mst.append((u,v,weight))iflen(mst)==len(vertices)-1:breakreturnmst

六、拓扑排序(用于有向无环图)

deftopological_sort_kahn(graph):"""Kahn算法实现拓扑排序"""# 计算入度in_degree={vertex:0forvertexingraph}foruingraph:forv,_ingraph[u]:in_degree[v]=in_degree.get(v,0)+1# 初始化队列queue=deque([vforvingraphifin_degree.get(v,0)==0])topo_order=[]whilequeue:u=queue.popleft()topo_order.append(u)forv,_ingraph.get(u,[]):in_degree[v]-=1ifin_degree[v]==0:queue.append(v)iflen(topo_order)==len(graph):returntopo_orderelse:# 图中存在环returnNonedeftopological_sort_dfs(graph):"""DFS实现拓扑排序"""visited=set()temp=set()# 临时标记,用于检测环stack=[]defdfs(vertex):ifvertexintemp:# 检测到环raiseValueError("图中有环,无法进行拓扑排序")ifvertexinvisited:returntemp.add(vertex)forneighbor,_ingraph.get(vertex,[]):dfs(neighbor)temp.remove(vertex)visited.add(vertex)stack.append(vertex)forvertexingraph:ifvertexnotinvisited:dfs(vertex)returnstack[::-1]

七、应用示例:社交网络分析

classSocialNetworkAnalyzer:def__init__(self):self.graph=GraphAdjList(directed=False)defadd_friendship(self,person1,person2,strength=1):self.graph.add_edge(person1,person2,strength)deffind_degrees_of_separation(self,start,target):"""使用BFS查找两个人之间的分离度数"""ifstart==target:return0visited=set([start])queue=deque([(start,0)])# (person, distance)whilequeue:current_person,distance=queue.popleft()forneighbor,_inself.graph.graph.get(current_person,[]):ifneighbor==target:returndistance+1ifneighbornotinvisited:visited.add(neighbor)queue.append((neighbor,distance+1))return-1# 没有路径deffind_influential_people(self,top_n=5):"""使用度中心性查找最有影响力的人"""centrality={}forpersoninself.graph.vertices:centrality[person]=len(self.graph.graph.get(person,[]))# 按中心性排序sorted_centrality=sorted(centrality.items(),key=lambdax:x[1],reverse=True)returnsorted_centrality[:top_n]deffind_communities(self):"""使用DFS查找连通分量(社区)"""visited=set()communities=[]forpersoninself.graph.vertices:ifpersonnotinvisited:community=dfs_recursive(self.graph.graph,person,set())visited.update(community)communities.append(community)returncommunities# 使用示例if__name__=="__main__":# 创建图graph=GraphAdjList()graph.add_edge(0,1,4)graph.add_edge(0,7,8)graph.add_edge(1,2,8)graph.add_edge(1,7,11)graph.add_edge(2,3,7)graph.add_edge(2,8,2)graph.add_edge(2,5,4)graph.add_edge(3,4,9)graph.add_edge(3,5,14)graph.add_edge(4,5,10)graph.add_edge(5,6,2)graph.add_edge(6,7,1)graph.add_edge(6,8,6)graph.add_edge(7,8,7)print("图结构:")graph.print_graph()print("\nDFS遍历 (从节点0开始):")dfs_recursive(graph.graph,0)print("\n\nBFS遍历 (从节点0开始):")bfs(graph.graph,0)print("\n\nDijkstra最短路径 (从节点0开始):")distances,previous=dijkstra(graph.graph,0)forvertexindistances:print(f"到节点{vertex}的最短距离:{distances[vertex]}")print(f"路径:{get_path(previous,vertex)}")print("\nPrim最小生成树:")mst_prim=prim_mst(graph.graph,0)print(f"最小生成树边:{mst_prim}")total_weight=sum(weightfor_,_,weightinmst_prim)print(f"总权重:{total_weight}")# 社交网络示例print("\n--- 社交网络分析示例 ---")social_net=SocialNetworkAnalyzer()social_net.add_friendship("Alice","Bob")social_net.add_friendship("Alice","Charlie")social_net.add_friendship("Bob","David")social_net.add_friendship("Charlie","David")social_net.add_friendship("David","Eve")social_net.add_friendship("Frank","Grace")print(f"Alice和Eve之间的分离度数:{social_net.find_degrees_of_separation('Alice','Eve')}")print(f"最有影响力的人:{social_net.find_influential_people(3)}")print(f"发现的社区:{social_net.find_communities()}")

八、总结与扩展
本文介绍了图的基本表示方法和几种核心算法。图算法的应用远不止于此,还包括:

网络流算法:如Ford-Fulkerson算法解决最大流问题

图匹配算法:如匈牙利算法解决二分图匹配

强连通分量:Kosaraju或Tarjan算法

图着色问题:用于调度和寄存器分配

旅行商问题:启发式算法如遗传算法、模拟退火

图算法的选择取决于具体问题:

对于无权图最短路径,使用BFS

对于有权图(非负权)最短路径,使用Dijkstra

对于负权图最短路径,使用Bellman-Ford

对于所有节点对最短路径,使用Floyd-Warshall

对于最小生成树,Prim适合稠密图,Kruskal适合稀疏图

理解这些基础算法是解决更复杂图问题的基础,也是许多实际应用的核心。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 15:05:47

朱炳仁、朱军岷14件铜艺捐赠入藏中国国家博物馆

2025年12月12日&#xff0c;朱炳仁、朱军岷作品捐赠入藏仪式在中国国家博物馆白玉厅隆重举行。这对国内罕见的“一门双国遗”父子传承人&#xff0c;将14件艺术珍品悉数捐赠给国博。这标志着朱炳仁首创的熔铜艺术&#xff0c;自2007年首件作品入藏国博后&#xff0c;历经18年沉…

作者头像 李华
网站建设 2026/10/8 2:28:20

数字化饮食闭环管理新趋势:AI技术如何重塑个性化营养方案

随着健康中国战略的深入推进&#xff0c;企业健康管理正迎来数字化转型升级的重要机遇。在员工健康管理领域&#xff0c;传统的饮食指导方式已难以满足精准化、个性化的需求。在此背景下&#xff0c;数字化饮食闭环管理作为一种创新模式&#xff0c;通过数据采集、智能分析、方…

作者头像 李华
网站建设 2026/10/8 12:21:54

AutoGPT+GPU云服务无限扩展的智能执行能力

AutoGPT 与 GPU 云服务&#xff1a;构建无限扩展的智能执行系统 在生成式 AI 的浪潮中&#xff0c;我们正经历一场从“对话工具”到“自主代理”的深刻变革。过去&#xff0c;用户需要一步步指导 AI 完成任务——“写一段介绍”、“搜索某项数据”、“总结这篇文档”。而今天&a…

作者头像 李华
网站建设 2026/10/8 15:54:22

Vim 标签页(Tab)操作详解

Vim 标签页&#xff08;Tab&#xff09;操作详解&#x1f4da; 标签页基础1. 创建标签页:tabnew [文件名] " 在新标签页打开文件 :tabedit [文件名] " 同上&#xff0c;在新标签页编辑文件 :tabe [文件名] " 简写形式" 从命令行直接…

作者头像 李华
网站建设 2026/10/7 10:47:28

学术突围新路径:书匠策AI如何成为毕业论文的“隐形导师“?

在高校图书馆的深夜灯光下&#xff0c;总有一群人对着电脑屏幕抓耳挠腮&#xff1a;文献综述像一团乱麻&#xff0c;实验数据在表格里打架&#xff0c;参考文献格式总在APA和GB之间反复横跳。这些场景&#xff0c;构成了无数毕业生挥之不去的"论文焦虑"。而今&#x…

作者头像 李华
网站建设 2026/10/7 11:17:54

K8s-1.29.2二进制安装-第一章

从本章来完成安装k8s学习的最后一种安装方式(二进制安装)&#xff0c;系统使用Rockly9.6&#xff0c;K8s版本1.29.2&#xff0c;一共会分成几张进行编写。1. 安装Topo2.环境初始化 1、镜像下载(所有节点) # 官方下载地址 https://rockylinux.org/download # 阿里云镜像下载地址…

作者头像 李华