数据结构-图

  • 图的定义:图(Graph)是由顶点(Vertex)和边(Edge)组成的数学结构具体概念见图的论述.
  • 图的存储
    • 邻接矩阵:图的邻接矩阵是一种用于表示图的存储结构,其中矩阵的行数和列数都对应于图的顶点,矩阵的元素表示顶点之间的边。在邻接矩阵中,如果顶点i与顶点j之间存在边,则矩阵的第i行第j列(记作aij)处的元素为1(或边的权重),否则为0。
    • 邻接表:邻接表是图的一种存储方式,用于表示图中的顶点之间的连接关系。在邻接表中,每个顶点都有一个列表,该列表包含了与该顶点直接相连的所有顶点。
    • 十字链表:十字链表是一种存储无向图或正则图的数据结构,它将图中每个顶点的邻接顶点按照字典序排列,并存储到两个列表中,分别称为该顶点的出度和入度列表。
    • 邻接多重表:邻接多重表是一种表示无向图或有权图的的数据结构。在这种数据结构中,每个顶点都有一个表,这个表记录了与该顶点相邻的所有顶点以及相邻的边。
  • 图的基本操作
    public class GraphDemo {private Map<String, List<String>> graph;public GraphDemo() {graph=new HashMap<>();}//添加节点public void addVertices(String name){graph.put(name,new ArrayList<>());}//添加边public void addEdge(String startName,String endName){if (graph.containsKey(startName)&&graph.containsKey(endName)){graph.get(startName).add(endName);}else {throw new RuntimeException("节点不存在");}}//删除节点public void removeVertex(String name){if (graph.containsKey(name)){List<String> neighbors = graph.get(name);for (String neighbor : neighbors) {graph.get(neighbor).remove(name);}graph.remove(name);}}//删除边public void removeEdge(String startName,String endName){if (graph.containsKey(startName)&&graph.containsKey(endName)){graph.get(startName).remove(endName);graph.get(endName).remove(startName);}}
    }
    
  • 图的遍历
    • 深度优先搜索(DFS):图的深度优先遍历(Depth-First Traversal)是一种用于遍历图的算法,它沿着一条路径尽可能深入,直到达到最深的顶点,然后回溯,再沿着另一条路径深入。这种算法适用于发现图中环、连通分量等性质,由于每个顶点和每条边都会被访问一次,所以时间复杂度是O(V+E)。。
          public void dfs(String startName){//创建栈Stack<String> stack = new Stack<>();stack.push(startName);while (!stack.isEmpty()){String vertex = stack.pop();System.out.println(vertex+" ");List<String> neighbors = graph.get(vertex);//遍历邻居节点for (String neighbor:neighbors){if (!stack.contains(neighbor)){stack.push(neighbor);}}}}
      
    • 广度优先搜索(BFS):广度优先搜索(Breadth-First Search,BFS)是一种用于图遍历或搜索的算法。与深度优先搜索(DFS)沿着一条路径尽可能深入不同,BFS采取一步一个顶点的方式进行搜索,即在每一层尽可能扩散得广,这段代码的时间复杂度是 O(V+E),其中 V 是顶点的数量,E 是边的数量。。
          public void bfs(String statName){Queue<String> queue = new LinkedList<>();queue.offer(statName);while (!queue.isEmpty()){String vetex = queue.poll();System.out.println(vetex+"");List<String> neighbors = graph.get(vetex);for (String neighbor:neighbors){if (!queue.contains(neighbor)){queue.add(neighbor);}}}}
      
    • 深度优先搜索的主要应用场景
      • 路径寻找:DFS 可以用来寻找从一个顶点到另一个顶点的路径。
      • 连通分量:DFS 可以用来找到图中的连通分量,即无法通过任何边连接的顶点集合。
      • 环检测:DFS 可以用来检测图中是否存在环。
      • 拓扑排序:DFS 可以用来进行拓扑排序,即对有向图进行顶点排序,使得对于任何一条边 (u, v),都满足 u 在 v 之前。
    • 广度优先搜索的主要应用场景
      • 寻找最短路径:BFS 可以用来寻找从源顶点到其他所有顶点的最短路径。
      • 查找特定距离的顶点:BFS 可以用来查找与源顶点距离为 k 的所有顶点。
      • 连通分量:BFS 可以用来找到图中的连通分量,与 DFS 类似,但 BFS 更适合处理较大的连通分量。
      • 网络延迟:BFS 可以用来计算网络延迟,即从源顶点到其他所有顶点的最短延迟。
  • 图的应用
    • 最小生成树:最小生成树(Minimum Spanning Tree,MST)是一棵包含图所有顶点的树形结构,并且它的边权之和尽可能小。这里的边权是指图中每条边的权重,权重越小说明树的边越短,树的高度也越小,从而整个树的路径长度也越小。
      求最小生成树的问题通常可以通过以下几种算法解决:
      • 普里姆算法(Prim algorithm):普里姆算法(Prim’s algorithm)是一种用于寻找加权无向图最小生成树的算法。最小生成树是一组边,它们连接了图中的所有顶点,且树中所有边的权值之和最小。
        以下是使用普里姆算法找到最小生成树的步骤:
        1. 创建一个包含所有顶点的集合,以及一个空的最小生成树集合。
        2. 从任意顶点开始,将其加入最小生成树集合中,并将其从所有顶点的集合中移除。
        3. 找到与当前最小生成树集合中顶点相邻的顶点中权值最小的顶点,将其加入最小生成树集合中,并将其从所有顶点的集合中移除。
        4. 重复步骤 3,直到所有顶点都被加入最小生成树集合中。
      • 克鲁斯卡尔算法(Kruskal algorithm):克鲁斯卡尔(Kruskal)算法是一种用来寻找最小生成树的算法。最小生成树是一棵包含图中所有顶点的树形结构,并且其边的权重之和尽可能小。
        克鲁斯卡尔算法的步骤如下:
        1. 将所有顶点构成若干个互不相交的子集,即每个顶点都是一个独立的连通分量。
        2. 将所有边按权重从小到大排序。
        3. 遍历排序后的边,对于每一条边,如果这条边连接的两个顶点属于不同的连通分量,则将这条边加入到最小生成树中,然后将这两个连通分量合并。
        4. 重复步骤 3,直到所有顶点都属于同一个连通分量。
        5. 此时,图中最小的生成树已经找齐。
      • 算法比较
        普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法在实现的所不同:
        1. 普里姆算法是一种贪心算法,其基本思想是:从一个顶点开始,每次选择与当前连通分量边界上权最小的边,将其加入连通分量中,并更新边界。这个过程会一直进行,直到所有顶点都被包含在连通分量中。克鲁斯卡尔算法是一种基于排序的算法。它首先将所有边按权重从小到大排序,然后遍历排序后的边,对于每一条边,如果这条边连接的两个顶点属于不同的连通分量,则将这条边加入到最小生成树中,然后将这两个连通分量合并。这个过程会一直进行,直到所有顶点都属于同一个连通分量。
        2. 数据结构:普里姆算法使用一个优先队列(最小堆)来存储待处理的边,而克鲁斯卡尔算法使用一个已排序的边列表。
        3. 时间复杂度:普里姆算法的时间复杂度是 O(V^2),其中 V 是顶点的数量。克鲁斯卡尔算法的时间复杂度是 O(ElogE),其中 E 是边的数量。在边数量较多时,克鲁斯卡尔算法通常比普里姆算法更快。
        4. 空间复杂度:普里姆算法需要维护一个优先队列,因此其空间复杂度与顶点数量成正比。克鲁斯卡尔算法需要维护一个已排序的边列表,因此其空间复杂度与边数量成正比。
        5. 适用性:普里姆算法适用于稠密图,因为其时间复杂度较低。克鲁斯卡尔算法适用于稀疏图,因为其时间复杂度较高。
      • 应用场景:最小生成树(Minimum Spanning Tree,MST)在许多实际场景中都有广泛应用,以下是一些常见的应用场景:
        • 通信网络设计:在构建通信网络时,需要确保所有节点之间都能互相通信,同时 minimize 总花费(例如,购买光纤、微波塔等)。
        • 路由表优化:在路由器中,最小生成树可以用于优化路由表,从而提高数据传输效率。
        • 图像处理:在图像处理中,最小生成树可以用于图像压缩、图像分割等任务。
    • 最短路径:最短路径问题是指在带权重的图中寻找从起点到终点的最短路径。在这个问题中,权重通常表示两点之间的距离或花费。
      • Dijkstra 算法:Dijkstra 算法是一种用于计算图中顶点之间最短路径的算法。它不适用于有负权边的图。算法步骤如下:
        1. 初始化距离数组 dist,将起点到其他所有顶点的距离设为无穷大,将起点到自身的距离设为 0。
        2. 创建一个优先队列(最小堆),将所有顶点及其距离放入队列。
        3. 当队列不为空时,取出队列中距离起点最近的顶点,并将其从队列中移除。
        4. 遍历当前顶点的所有邻接顶点,计算从起点到邻接顶点的距离,如果该距离小于已知的最短距离,则更新最短距离,并将该邻接顶点压入队列。
        5. 重复步骤 3 和 4,直到队列为空。
      • Floyd-Warshall 算法是一种用于计算图中所有顶点之间最短路径的算法。它适用于有负权边的图。以下是 Floyd-Warshall 算法的步骤:
        1. 初始化距离矩阵 dist,将图中所有顶点之间的距离初始化为无穷大,将起点到其他所有顶点的距离设为有向边或无向边的权值,节点到自己的距离为0。
        2. 以三个顶点的有向图为例,先将V[0]作为中间结点若dist[i][j]的值大于dist[i][0]+dist[0][j]则更新dist[i][j]的值.
        3. 以此类推直到所有的节点都遍历一遍.
      • 算法比较
        • 复杂度:Dijkstra 算法的复杂度为 O(V^2),而 Floyd-Warshall 算法的复杂度为 O(V^3)。
        • 更新最短路径的方式:在 Dijkstra 算法中,我们通过比较顶点的距离值来更新最短路径;在 Floyd-Warshall 算法中,我们通过遍历所有顶点来更新最短路径。
        • 算法实现方式:Dijkstra 算法使用优先队列(最小堆)来存储待处理的顶点,而 Floyd-Warshall 算法使用二维距离矩阵来存储顶点之间的最短距离。
        • 适用性:Dijkstra 算法不适用于有负权边的图,而 Floyd-Warshall 算法适用于有负权边的图。
      • 应用场景
        • 文件传输:在文件传输过程中,需要计算两点之间的最短路径,以便选择最优的传输路径,以提高传输速度和减少传输成本。
        • 网络通信:在网络通信中,需要计算两点之间的最短路径,以便数据包能够以最短的时间从源节点到达目标节点。
        • 算法研究:最短路径问题是一种重要的算法问题,是许多算法研究的基础。在计算机上,可以进行最短路径算法的模拟和优化研究。
        • 游戏设计:在游戏设计中,最短路径问题可以用于计算角色移动的最短路径,以便设计更合理的游戏关卡和路径。
        • 人工智能:在人工智能中,最短路径问题可以用于计算机器人移动的最短路径,以便实现机器人的自主导航和路径规划。
    • 拓扑排序
      • 什么是AOV网:AOV(Activity On Vertex)网是一种用顶点表示活动,用边表示活动之间依赖关系的网络。它主要用于表示工程中的任务及其依赖关系,以便进行项目计划和进度控制。在 AOV 网中,每个顶点表示一个活动,每条边表示两个活动之间的依赖关系。例如,活动 A 在活动 B 之前完成,那么在 AOV 网中,从顶点 A 到顶点 B 有一条有向边。
      • 什么是拓扑排序:拓扑排序是对有向无环图的顶点的一种排序,他使得若只存在一条从a到b的路径,那排序中b出现在a的后面.
      • 对aov网排序的步骤
        • 初始化一个队列,用于存储待处理的顶点。
        • 遍历图中的所有顶点,将入度为0的顶点加入队列。
        • 当队列不为空时,取出队列中的顶点,并将其从图中删除。然后,遍历该顶点的所有邻接顶点,将它们的入度减1。如果减1后入度为0,则将该邻接顶点加入队列。
        • 重复步骤3,直到队列为空。
      • 应用场景:
        • 项目计划和进度控制:在项目管理中,可以使用拓扑排序来确定任务的优先级,以便按照合理的顺序完成任务。
        • 网络通信:在网络通信中,可以使用拓扑排序来确定数据包的传输顺序,以便按照合理的路径传输数据。
        • 算法研究:拓扑排序是一种重要的算法问题,是许多算法研究的基础。在计算机科学领域,可以进行拓扑排序的模拟和优化研究。
        • 游戏设计:在游戏设计中,可以使用拓扑排序来确定角色移动的顺序,以便设计更合理的游戏关卡和路径。
    • 判断无环图
      • 判断无环图的过程:
        1. 从一个节点出发,遍历所有周围节点,将遍历过的节点加入visited数组和stack栈中
        2. 每次遍历都是将节点和节点的临近节点以此递归下去进行遍历,同时加入stack栈中,若栈在某次递归中包含了某个节点,说明形成了一个闭环,则直接返回false
        3. 否则当所有的临近节点都访问过后将stack栈清楚.
        4. 返回到过程a(因为可能存在其他联通分量)
              //DFS判断无环图public boolean dfs(String vetex,Map<String,Boolean> visited,Map<String,Boolean> stack){//判断是否包含在栈中if (stack.containsKey(vetex)){return true;}//判断是否被访问过if (visited.containsKey(vetex)){return false;}visited.put(vetex,true);stack.put(vetex,true);for (String neighbor:graph.get(vetex)){if (dfs(neighbor,visited,stack)){return true;}}stack.remove(vetex);return false;}public boolean hasCycle(){//创建记录对象HashMap<String,Boolean> visited = new HashMap<>();//遍历所有节点for (String vetex:graph.keySet()){//如果节点未被访问过if (!visited.containsKey(vetex)){if (dfs(vetex,visited,new HashMap<>())){return true;}}}return false;}
          
       //BFS判断无环图public boolean bfs(String vertex,Map<String,Boolean> visites,Queue<String> queue){visites.put(vertex,true);queue.add(vertex);while (!queue.isEmpty()){String current=queue.poll();for (String neighbor:graph.get(current)){//若没访问过if (!visites.containsKey(neighbor)){visites.put(neighbor,true);queue.add(neighbor);//已经访问过}else {return true;}}}return false;}public boolean hasCycle2(){HashMap<String,Boolean> visited = new HashMap<>();Queue<String> queue = new LinkedList<>();for (String vertex:graph.keySet()){if (!visited.containsKey(vertex)){if (bfs(vertex,visited,queue)){return true;}}}return false;}
    
    • 关键路径
      • AOE网:AOE(Activity On Edge)网是一种用于表示活动及其依赖关系的图。它通过边表示活动,通过顶点表示活动之间的依赖关系。AOV网的边无权值,AOE网的边有权值.
      • 关键路径,关键活动:把具有最大路径长度的路径称为关键路径,而把关键路径上的活动称为关键活动.
  • 图的实际应用场景
    • 社交网络:图可以用来表示社交网络中的用户及其之间的关系。例如,Facebook 使用图结构来存储用户及其好友之间的关系,以便快速推荐可能认识的人、找到共同好友等。
    • 推荐系统:图可以用来表示用户与物品之间的交互关系,例如用户购买商品、给商品打分等。通过分析这些关系,可以构建推荐系统,为用户提供个性化的推荐。
    • 地图导航:图可以用来表示地图上的道路网络,节点表示道路交叉点,边表示道路连接。通过使用图数据结构,可以实现地图导航功能,例如计算最短路径、推荐路线等。
    • 知识图谱:图可以用来表示实体(如人物、地点、组织等)及其之间的关系。例如,Google 的 Knowledge Graph 就是一个大规模的知识图谱,用于提供关于实体及其关系的详细信息。
    • 机器学习:图在机器学习中用于表示数据集中的对象及其之间的关系。例如,图神经网络(GNN)是一种针对图数据的深度学习模型,可以用于学习图上的特征,并用于预测和分类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/822155.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UbuntuServer22.04安装docker

通过ubuntuserver安装docker是搭建开发环境最便捷的方式之一。下面介绍一下再ubuntu22.04上如何安装docker。相关内容参考官网链接&#xff1a;Install Docker Engine on Ubuntu 根据官网推荐&#xff0c;利用apt命令的方式安装&#xff0c;首先需要设置docker仓库&#xff0c…

【Android AMS】startActivity流程分析

文章目录 AMSActivityStackstartActivity流程startActivityMayWaitstartActivityUncheckedLocked startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition)resumeTopActivityLocked 参考 AMS是个用于管理Activity和其它组件运行…

贴片滚珠振动开关 / 振动传感器的用法

就是这种小东西&#xff1a; 上面的截图来自&#xff1a;https://item.szlcsc.com/3600130.html 以前写过一篇介绍这种东西内部的结构原理&#xff1a;贴片微型滚珠振动开关的结构原理。就是有个小滚珠会接通开关两边的电极&#xff0c;振动时滚珠会在内部蹦跳&#xff0c;开关…

手把手教你设计报表,轻松做出一份美观又实用的报表

你是不是在看着自己的呆板、没有特色的报表而深感苦恼&#xff0c;但同事却可以使用同样的数据制作并且展现出多样化的丰富美观的报表。要知道&#xff0c;除了要达成数据的准确度&#xff0c;基本的数据分析维度需求之外&#xff0c;报表的美观程度也有众多的隐藏“福利”与好…

自定义类似微信效果Preference

1. 为自定义Preference 添加背景&#xff1a;custom_preference_background.xml <?xml version"1.0" encoding"utf-8"?> <selector xmlns:android"http://schemas.android.com/apk/res/android"><item><shape android:s…

LRTimelapse for Mac:专业延时摄影视频制作利器

LRTimelapse for Mac是一款专为Mac用户设计的延时摄影视频制作软件&#xff0c;它以其出色的性能和丰富的功能&#xff0c;成为摄影爱好者和专业摄影师的得力助手。 LRTimelapse for Mac v6.5.4中文激活版下载 这款软件提供了直观易用的界面&#xff0c;用户可以轻松上手&#…

【从浅学到熟知Linux】进程控制下篇=>进程程序替换与简易Shell实现(含替换原理、execve、execvp等接口详解)

&#x1f3e0;关于专栏&#xff1a;Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程等内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 进程程序替换什么是程序替换及其原理替换函数execlexeclpexecleexecvexecvpexecvpeexecve 替换函数总结实现…

宝剑锋从磨砺出,透视雀巢咖啡品牌焕新与产品升级的想象力

自1989年进入中国市场以来&#xff0c;陪伴着国内咖啡行业由启蒙期走向兴盛期的雀巢咖啡&#xff0c;始终坚持以消费者高品质、个性化需求为本位&#xff0c;在保有独特性的基础上持续创新&#xff0c;实现了从无到有的攻克与突破。 近日&#xff0c;深耕中国三十六载的雀巢咖…

康耐视visionpro-CogCreateLinePerpendicularTool操作操作工具详细说明

CogCreateLinePerpendicularTool]功能说明&#xff1a; 创建点到线的垂线 CogCreateLinePerpendicularTool操作说明&#xff1a; ①.打开工具栏&#xff0c;双击或点击扇标拖拽添加CogCreateLinePerpendicularTool ②.添加输入源&#xff1a;右键“链接到”或以连线拖 拽的方式…

Java代码基础算法练习-圆的面积-2024.04.17

任务描述&#xff1a; 已知半径r&#xff0c;求一个圆的面积(保留两位小数)&#xff0c;其中 0 < r < 5&#xff0c;PI 3.14&#xff0c;圆面积公式: PI * r * r 任务要求&#xff1a; 代码示例&#xff1a; package April_2024;import java.util.Scanner;// 已知半径…

【前端】1. HTML【万字长文】

HTML 基础 HTML 结构 认识 HTML 标签 HTML 代码是由 “标签” 构成的. 形如: <body>hello</body>标签名 (body) 放到 < > 中大部分标签成对出现. <body> 为开始标签, </body> 为结束标签.少数标签只有开始标签, 称为 “单标签”.开始标签和…

Linux-时间同步服务器

1. (问答题) 一.配置server主机要求如下&#xff1a; 1.server主机的主机名称为 ntp_server.example.com 编写脚本文件 #!/bin/bash hostnamectl hostname ntp_server.example.com cd /etc/NetworkManager/system-connections/ rm -fr * cat > eth0.nmconnection <&…

【编译原理】02词法分析(1)

接上篇 &#xff1a;【编译原理】01引论 词法分析是编译过程中将字符流转换成为符号流的一个工作阶段&#xff0c;是编译的第一步工作&#xff0c;其后续工作是语法分析。 词法分析的输入是源代码&#xff1b; 词法分析的输出是符号流&#xff1b; 词法分析需要识别词法错误&am…

STM32 软件I2C方式读取MT6701磁编码器获取角度例程

STM32 软件I2C方式读取MT6701磁编码器获取角度例程 &#x1f4cd;相关篇《STM32 软件I2C方式读取AS5600磁编码器获取角度例程》&#x1f33f;《Arduino通过I2C驱动MT6701磁编码器并读取角度数据》&#x1f530;MT6701芯片和AS5600从软件读取对比&#xff0c;只是读取的寄存器和…

代码随想录算法训练营第56天| 583. 两个字符串的删除操作|72. 编辑距离|编辑距离总结篇

代码随想录算法训练营第56天| 583. 两个字符串的删除操作|72. 编辑距离|编辑距离总结篇 详细布置 583. 两个字符串的删除操作 本题和动态规划&#xff1a;115.不同的子序列 相比&#xff0c;其实就是两个字符串都可以删除了&#xff0c;情况虽说复杂一些&#xff0c;但整体思…

【Redis 神秘大陆】009 案例实践进阶

九、案例实践&进阶方案 9.1 本地缓存组件选型 使用缓存组件时需要重点关注集群方式、集群、缓存命中率。 需要关注集群组建方式、缓存统计&#xff1b;还需要考虑缓存开发语言对缓存的影响&#xff0c;如对于JAVA开发的缓存需要考虑GC的影响&#xff1b;最后还要特别关注…

SQL优化——核心概念

文章目录 1、基数(数据分布)2、选择性3、直方图&#xff08;HISTOGRAM&#xff09;4、回表&#xff08;TABLE ACCESS BY INDEX ROWID&#xff09;5、集群因子&#xff08;CLUSTERING FACTOR&#xff09;6、表与表之间关系 1、基数(数据分布) 某个列唯一键&#xff08;Distinct…

springboot整合dubbo实现RPC服务远程调用

一、dubbo简介 1.什么是dubbo Apache Dubbo是一款微服务开发框架&#xff0c;他提供了RPC通信与微服务治理两大关键能力。有着远程发现与通信的能力&#xff0c;可以实现服务注册、负载均衡、流量调度等服务治理诉求。 2.dubbo基本工作原理 Contaniner:容器Provider&#xf…

[AI]-(第0期):认知深度学习

深度学习是一种人工智能&#xff08;AI&#xff09;方法&#xff0c;用于教计算机以受人脑启发的方式处理数据。 深度学习模型可以识别图片、文本、声音和其他数据中的复杂模式&#xff0c;从而生成准确的见解和预测。 您可以使用深度学习方法自动执行通常需要人工智能完成的…

【C++】set 类 和 map 类

1. 关联式容器 关联式容器也是用来存储数据的&#xff0c;与序列式容器不同的是&#xff0c;其里面存储的是<key, value>结构的 键值对&#xff0c;在数据检索时比序列式容器效率更高 2. 键值对 用来表示具有一一对应关系的一种结构&#xff0c;该结构中一般只包含…