14.6 普里姆算法

14.6.1 应用场景-修路问题

看一个应用场景和问题:

  1. 有胜利乡有 7 个村庄(A, B, C, D, E, F, G) ,现在需要修路把 7 个村庄连通
  2. 各个村庄的距离用边线表示(权) ,比如 A – B 距离 5 公里
  3. 问:如何修路保证各个村庄都能连通,并且总的修建公路总里程最短?
    思路: 将 10 条边,连接即可,但是总的里程数不是最小。

正确的思路,就是尽可能的选择少的路线,并且每条路线最小,保证总里程数最少。
这个问题我们一会在解决,先来看看普里姆算法相关的东西。

14.6.2 最小生成树

修路问题本质就是就是最小生成树问题, 先介绍一下最小生成树(Minimum Cost Spanning Tree),简称 MST。给定一个带权的无向连通图,如何选取一棵生成树,使树上所有边上权的总和为最小,这叫最小生成树

  1. N 个顶点,一定有 N-1 条边

  2. 包含全部顶点

  3. N-1 条边都在图中

  4. 举例说明(如图)

  5. 求最小生成树的算法主要是普里姆算法和克鲁斯卡尔算法

14.6.3 普里姆算法介绍

普利姆(Prim)算法求最小生成树,也就是在包含 n 个顶点的连通图中,找出只有(n-1)条边包含所有 n 个顶点的连通子图,也就是所谓的极小连通子图
普利姆的算法如下:

  1. 设 G=(V,E)是连通网,T=(U,D)是最小生成树,V,U 是顶点集合,E,D 是边的集合
  2. 若从顶点 u 开始构造最小生成树,则从集合 V 中取出顶点 u 放入集合 U 中,标记顶点 v 的 visited[u]=1
  3. 若集合 U 中顶点 ui 与集合 V-U 中的顶点 vj 之间存在边,则寻找这些边中权值最小的边,但不能构成回路,将顶点 vj 加入集合 U 中,将边(ui,vj)加入集合 D 中,标记 visited[vj]=1
  4. 重复步骤②,直到 U 与 V 相等,即所有顶点都被标记为访问过,此时 D 中有 n-1 条边
  5. 提示: 单独看步骤很难理解,我们通过代码来讲解,比较好理解。
  6. 图解普利姆算法

    接下来我们真正解决修路问题

14.6.4 普里姆算法最佳实践(修路问题)


问题:

  1. 有胜利乡有 7 个村庄(A, B, C, D, E, F, G) ,现在需要修路把 7 个村庄连通
  2. 各个村庄的距离用边线表示(权) ,比如 A – B 距离 5 公里
  3. 问:如何修路保证各个村庄都能连通,并且总的修建公路总里程最短?

代码实现

import java.util.Arrays;
/*** @author zk* @version 1.0.0* @ClassName PrimAlgorithm.java* @Description TODO 普利姆算法求最小生成树(修路问题,求总长最小的方案)* @createTime 2021年09月30日 15:29:00*/
public class PrimAlgorithm {public static void main(String[] args) {//测试看看图是否创建 okchar[] data = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G'};int vertex = data.length;//邻接矩阵的关系使用二维数组表示,10000 这个大数,表示两个点不联通int[][] weight = new int[][]{{10000, 5, 7, 10000, 10000, 10000, 2},{5, 10000, 10000, 9, 10000, 10000, 3},{7, 10000, 10000, 10000, 8, 10000, 10000},{10000, 9, 10000, 10000, 10000, 4, 10000},{10000, 10000, 8, 10000, 10000, 5, 4},{10000, 10000, 10000, 4, 5, 10000, 6},{2, 3, 10000, 10000, 4, 6, 10000},};//创建 MGraph 对象MGraph graph = new MGraph(vertex);//创建一个 MinTree 对象MinTree minTree = new MinTree();minTree.createGraph(graph, vertex, data, weight);//输出minTree.showGraph(graph);//测试普利姆算法minTree.prim(graph, 1);//}
}class MinTree {//创建图的邻接矩阵/*** @param graph  图对象* @param vertex 图对应的顶点个数* @param data   图的各个顶点的值* @param weight 图的邻接矩阵*/public void createGraph(MGraph graph, int vertex, char[] data, int[][] weight) {for (int i = 0; i < vertex; i++) {graph.data[i] = data[i];for (int j = 0; j < vertex; j++) {graph.weight[i][j] = weight[i][j];}}}//显示图的邻接矩阵public void showGraph(MGraph graph) {for (int[] link : graph.weight) {System.out.println(Arrays.toString(link));}System.out.println();}//编写 prim 算法,得到最小生成树/*** @param graph 图* @param v     表示从图的第几个顶点开始生成'A'->0 'B'->1...*/public void prim(MGraph graph, int v) {//visited[] 默认元素的值都是 0, 表示没有访问过  /visited[] 默认元素的值都是 0, 表示没有访问int[] visited = new int[graph.vertex];// 把当前节点标记为已访问visited[v] = 1;// h1和h2 记录两个顶点的下表int h1 = -1;int h2 = -1;int minWeight = 10000; // 将minWeight 初始成一个大数,后面遍历的时候会被替换for (int k = 1; k < graph.vertex; k++) { //因为有 graph.verxs 顶点,普利姆算法结束后,有 graph.vertex-1 边for (int i = 0; i < graph.vertex; i++) {for (int j = 0; j < graph.vertex; j++) {if (visited[i] == 1 && visited[j] == 0 && graph.weight[i][j] < minWeight) {minWeight = graph.weight[i][j];h1 = i;h2 = j;}}}System.out.println("边<" + graph.data[h1] + "," + graph.data[h2] + "> 权值:" + minWeight);visited[h2] = 1;minWeight = 10000;}}
}class MGraph {int vertex; // 表示图的节点个数char[] data; // 存放节点数据int[][] weight; // 存放边,就是我们的邻接矩阵public MGraph(int vertex) {this.vertex = vertex;this.data = new char[vertex];weight = new int[vertex][vertex];}
}

Java用普里姆算法(prim)解决修路最短路径问题相关推荐

  1. (数据结构)图的最小生成树 普里姆算法(Prim)

    假设要在n个城市之间建立通信联络网,每两个城市之间建立线路都需要花费不同大小的经费,则连通n个城市只需要n-1个条线路,最小生成树解决的问题就是:如何在最节省经费的前提下建立这个通信网 也可以理解为: ...

  2. 普里姆算法(Prim)和克鲁斯卡尔(Kruskal)算法

    普里姆算法(Prim)和克鲁斯卡尔(Kruskal)算法 普里姆算法的基本思想: 取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w.添加顶点w的条件为:w 和已在生成树上的顶点v ...

  3. 【算法】普里姆算法 Prim算法解决修路问题

    文章目录 1. 概述 1.1 最小生成树 2.普里姆算法介绍 3.代码 3.1 案例1 1. 概述 视频:https://www.bilibili.com/video/BV1E4411H73v?p=1 ...

  4. java实现普里姆算法

    算法步骤: 设 G=(V,E)是连通网, T=(U,D)是最小生成树, V,U 是顶点集合, E,D 是边的集合 若从顶点 u 开始构造最小生成树, 则从集合 V 中取出顶点 u 放入集合 U 中, ...

  5. (迪杰斯特拉)Dijkstra算法 与 普里姆算法(Prim算法)

    怎么硕呢 这俩肯定是一个人抄了另一个人的代码.就在花费那一部分  一个是d[u] = mp[u][v]+d[v] (迪杰斯特拉)  另一个是d[u] = mp[u][v] 大体思路就是一直找和以之节点 ...

  6. 最小生成树普里姆算法Prim

    目录 前言 一.Prim算法的基本思路 二.代码实现 总结 前言   无论是什么程序都要和数据打交道,一个好的程序员会选择更优的数据结构来更好的解决问题,因此数据结构的重要性不言而喻.数据结构的学习本 ...

  7. 普里姆(Prim)算法 Java实现(最小生成树)

    构造最小生成树的Prim算法(从顶点的思想) 自己的话描述: 1. 从任意一个顶点开始.临时权值数组就是该顶点的权值数组. 2. 找到一条权重最小的边,然后把这两个顶点视为一个顶点,新加入的顶点在临时 ...

  8. Java普利姆算法(Prim)与克鲁斯卡尔算法(Kruskal)

    1.Java普利姆算法(Prim)与克鲁斯卡尔算法(Kruskal) 普利姆算法(Prim)与克鲁斯卡尔算法(Kruskal)求**最小生成树(极小连通子图)**的算法 1.1普利姆算法(Prim) ...

  9. 最小生成树(普里姆算法【Prim】与克鲁斯卡尔算法【Kruskal】)

    写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...

最新文章

  1. 浅析:seo工程师擅长的网站数据分析
  2. 静态布局、自适应布局、流式布局、响应式布局、弹性布局简析、BFC
  3. ios-晋级之路 CocoaPods引用第三方库不import不自动补齐
  4. 用css样式画三角形(提示框三角形)
  5. Codeforces Round #315 (Div. 1) A. Primes or Palindromes? 暴力
  6. 泸州市的电子计算机学校名称,泸州电子计算机机械学校2020年招生简介
  7. html5 datalist 选中option选项后的触发事件
  8. BZOJ1076: [SCOI2008]奖励关【状压DP+期望DP】
  9. 主成分分析法怎么提取图片中的字_视频图像的MATLAB处理(2)两种主成分分析方法...
  10. 动易 dw css不对,动易模板常用CSS修改实际操作技巧
  11. 张鑫旭的《CSS世界》读后笔记
  12. gif动画录制工具_9种优化动画GIF的最佳工具
  13. Arcgis报错 ERROR 999999的解决方法汇总
  14. java开发一般用se,用大白話聊聊JavaSE
  15. Cloudera 的开放湖仓采用dbt Core增压
  16. 使用HbuilderX 的UNIapp开发app, 打包后定位不能使用的解决方式
  17. centos android模拟器,centos 7 安装android 模拟器genymotion
  18. 1080MOOC期中成绩
  19. 看完这五个问题后你真的了解C语言吗?(深度剖析C语言第二期)
  20. 计算机辅助设计绘图员一级,计算机辅助设计绘图员(AUTO CAD)中级证简介

热门文章

  1. 在AD17中如何自定义板子大小
  2. HanLP 自然语言处理 for nodejs 1
  3. opencv手写数字识别(未完待续...)
  4. BP 神经网络的数据分类
  5. 如何使用DEV-C++(超详细)
  6. 麦克尼马尔检验(McNemar test)
  7. 微信 拒绝共享位置服务器,微信共享位置结束不了怎么办?如何解决问题?
  8. Windows下Apache连接Tomcat(64位)
  9. 电视剧中一看就让人崩溃的镜头大全~
  10. Unix时间戳和北京时间的相互转换(C语言实现 )