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

图的表示以及基础操作

图其实有很多应用,现实系统可以用图来建模,相应的问题也可以约化为图计算问题。

图(graph)是一种非线性数据结构,由顶点(vertex)和边(edge)组成。我们可以将图
图G 抽象地表示为一组顶点V 和一组边E 的集合。

如果将顶点看作节点,将边看作连接各个节点的引用(指针),我们就可以将图看作一种从链表拓展而来的数据结构。相较于线性关系(链表)和分治关系(树),网络关系(图)的自由度更高,因而更为复杂。

图的表示
1,邻接矩阵
设图的顶点数量为 n ,邻接矩阵(adjacency matrix)使用一个 n乘以n大小的矩阵来表示图,每一行(列)代表一个顶点,矩阵元素代表边,用 1 或 0表示两个顶点之间是否存在边。设邻接矩阵为 M、顶点列表为 V ,那么矩阵元素 M[i,j]=1表示顶点 V[i]到顶点 V[j] 之间存在边,反之 M[i,j]=0表示两顶点之间无边。

顶点不能与自身相连,此时邻接矩阵主对角线元素没有意义。对于无向图,两个方向的边等价,此时邻接矩阵关于主对角线对称。将邻接矩阵的元素从 1 和 0替换为权重,则可表示有权图。使用邻接矩阵表示图时,我们可以直接访问矩阵元素以获取边,因此增删查改操作的效率很高,时间复杂度均为 O(1)。然而,矩阵的空间复杂度为O(n平方) ,内存占用较多。
基于邻接矩阵的基础操作

/* 基于邻接矩阵实现的无向图类 */classGraphAdjMat{List<Integer>vertices;// 顶点列表,元素代表“顶点值”,索引代表“顶点索引”List<List<Integer>>adjMat;// 邻接矩阵,行列索引对应“顶点索引”/* 构造方法 */publicGraphAdjMat(int[]vertices,int[][]edges){this.vertices=newArrayList<>();this.adjMat=newArrayList<>();// 添加顶点for(intval:vertices){addVertex(val);}// 添加边// 请注意,edges 元素代表顶点索引,即对应 vertices 元素索引for(int[]e:edges){addEdge(e[0],e[1]);}}/* 获取顶点数量 */publicintsize(){returnvertices.size();}/* 添加顶点 */publicvoidaddVertex(intval){intn=size();// 向顶点列表中添加新顶点的值vertices.add(val);// 在邻接矩阵中添加一行List<Integer>newRow=newArrayList<>(n);for(intj=0;j<n;j++){newRow.add(0);}adjMat.add(newRow);// 在邻接矩阵中添加一列for(List<Integer>row:adjMat){row.add(0);}}/* 删除顶点 */publicvoidremoveVertex(intindex){if(index>=size())thrownewIndexOutOfBoundsException();// 在顶点列表中移除索引 index 的顶点vertices.remove(index);// 在邻接矩阵中删除索引 index 的行adjMat.remove(index);// 在邻接矩阵中删除索引 index 的列for(List<Integer>row:adjMat){row.remove(index);}}/* 添加边 */// 参数 i, j 对应 vertices 元素索引publicvoidaddEdge(inti,intj){// 索引越界与相等处理if(i<0||j<0||i>=size()||j>=size()||i==j)thrownewIndexOutOfBoundsException();// 在无向图中,邻接矩阵关于主对角线对称,即满足 (i, j) == (j, i)adjMat.get(i).set(j,1);adjMat.get(j).set(i,1);}/* 删除边 */// 参数 i, j 对应 vertices 元素索引publicvoidremoveEdge(inti,intj){// 索引越界与相等处理if(i<0||j<0||i>=size()||j>=size()||i==j)thrownewIndexOutOfBoundsException();adjMat.get(i).set(j,0);adjMat.get(j).set(i,0);}/* 打印邻接矩阵 */publicvoidprint(){System.out.print("顶点列表 = ");System.out.println(vertices);System.out.println("邻接矩阵 =");PrintUtil.printMatrix(adjMat);}}

邻接表(adjacency list)使用 n个链表来表示图,链表节点表示顶点。第 i个链表对应顶点 i,其中存储了该顶点的所有邻接顶点(与该顶点相连的顶点)。

邻接表仅存储实际存在的边,而边的总数通常远小于 ,因此它更加节省空间。然而,在邻接表中需要通过遍历链表来查找边,因此其时间效率不如邻接矩阵。
基于邻接表的基础操作

/* 基于邻接表实现的无向图类 */classGraphAdjList{// 邻接表,key:顶点,value:该顶点的所有邻接顶点Map<Vertex,List<Vertex>>adjList;/* 构造方法 */publicGraphAdjList(Vertex[][]edges){this.adjList=newHashMap<>();// 添加所有顶点和边for(Vertex[]edge:edges){addVertex(edge[0]);addVertex(edge[1]);addEdge(edge[0],edge[1]);}}/* 获取顶点数量 */publicintsize(){returnadjList.size();}/* 添加边 */publicvoidaddEdge(Vertexvet1,Vertexvet2){if(!adjList.containsKey(vet1)||!adjList.containsKey(vet2)||vet1==vet2)thrownewIllegalArgumentException();// 添加边 vet1 - vet2adjList.get(vet1).add(vet2);adjList.get(vet2).add(vet1);}/* 删除边 */publicvoidremoveEdge(Vertexvet1,Vertexvet2){if(!adjList.containsKey(vet1)||!adjList.containsKey(vet2)||vet1==vet2)thrownewIllegalArgumentException();// 删除边 vet1 - vet2adjList.get(vet1).remove(vet2);adjList.get(vet2).remove(vet1);}/* 添加顶点 */publicvoidaddVertex(Vertexvet){if(adjList.containsKey(vet))return;// 在邻接表中添加一个新链表adjList.put(vet,newArrayList<>());}/* 删除顶点 */publicvoidremoveVertex(Vertexvet){if(!adjList.containsKey(vet))thrownewIllegalArgumentException();// 在邻接表中删除顶点 vet 对应的链表adjList.remove(vet);// 遍历其他顶点的链表,删除所有包含 vet 的边for(List<Vertex>list:adjList.values()){list.remove(vet);}}/* 打印邻接表 */publicvoidprint(){System.out.println("邻接表 =");for(Map.Entry<Vertex,List<Vertex>>pair:adjList.entrySet()){List<Integer>tmp=newArrayList<>();for(Vertexvertex:pair.getValue())tmp.add(vertex.val);System.out.println(pair.getKey().val+": "+tmp+",");}}}```
http://www.cnnetsun.cn/news/20554.html

相关文章:

  • 继电器:电力安全的隐形守护者
  • R.swift终极配置指南:构建强类型资源管理系统的完整实践
  • 联邦学习赋能YOLOv5:计算机视觉的隐私保护新范式
  • 从卡顿到丝滑:我的酷安桌面化使用体验
  • kmp算法
  • AgentHub更新:LangGraph+千问实现Adaptive RAG系统
  • 快速掌握RustFS分布式存储监控告警系统:从异常检测到智能通知的完整指南
  • Steamless终极指南:轻松移除Steam游戏DRM保护
  • 图像对比工具在网络安全配置中的高效应用与优化策略
  • 终极指南:macOS iSCSI Initiator快速连接远程存储
  • 在.NET Framework 4.7.2 使用Microsoft.Practices.EnterpriseLibrary.Data配置出错
  • 【论文自动阅读】HIERARCHICAL MIXTURE-OF-EXPERTS FOR GENERALIST VISION-LANGUAGE-ACTION POLICIES
  • FastDepth:嵌入式系统上的快速单目深度估计
  • Solidity 中的using for详解
  • GPT-5.2 的数据基石、原生多模态与隐私承诺的深度考量
  • 开源代码智能体SWE-Dev-9B崛起:逼近GPT-4o性能,90%工程师效率革命加速
  • Wasmer WebAssembly运行时终极指南:从零到实战部署
  • 2025年推荐一些程序员常逛的开发者社区
  • ExplorerPatcher深度解析:重塑Windows界面体验的终极方案
  • SketchUp STL插件实战指南:打通3D打印的最后一公里
  • 基于VUE技术的健康监测可视化系统设计与实现开题报告
  • 基于VUE技术的健康监测可视化系统设计与实现任务书
  • Smithbox游戏修改工具:从玩家痛点出发的7大深度解决方案
  • Qt + VS2017 编译缺少库,在对方设备无法运行,推荐几种做法。
  • 窗口管理大师:WindowResizer完整使用指南
  • 20亿参数撬动工业质检革命:Isaac-0.1开启边缘智能新纪元
  • 基于web的超市管理系统开题报告
  • Driver.js 1.x升级攻略:告别旧版,拥抱全新API设计
  • Laudspeaker:终极开源客户参与平台完全指南
  • 20、Snort Options and iptables Packet Filtering