目录

  • 1. 最小生成树的介绍
  • 2. 普里姆算法的介绍
  • 3. 修路问题的介绍

1. 最小生成树的介绍

最小生成树(Minimum Cost Spanning Tree),简称MST。给定一个带权的无向连通图, 选取一棵生成树, 生成树所有顶点都能连通但不能形成回路。使树上所有边的权的总和为最小, 就是最小生成树。如下所示:


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

实现最小生成树的算法主要有普里姆算法克鲁斯卡尔算法

2. 普里姆算法的介绍

普利姆(Prim)算法求最小生成树,就是在包含N个顶点的完全图中,找出只有(N-1)条边且包含所有N个顶点的最小总权重值的连通子图

思路如下:

  1. 对于第一顶点,直接标记为已访问
  2. 找出所有边,其中一个顶点已访问,另一个顶点未访问。取权重值最小的一条边,并将该条边的未访问的顶点标记为已访问
  3. 不断的重复步骤2,直到所有顶点都被访问

3. 修路问题的介绍


问题:有7个村庄A、B、C、D、E、F、G,各个村庄之间的距离(权)用边线表示,比如A -> B距离5公里。如何让各个村庄都能连通,并且总的修路里程最短

基本思路:尽可能少的选择路线,并且选择的路线距离最短,才能保证总的修路里程数最短

程序如下:

import java.util.Arrays;public class PrimAlgorithm {public static void main(String[] args) {// 顶点集合char[] vertexs = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G'};// 顶点个数int vertexNum = vertexs.length;// N个顶点形成的N * N二维数组,用来保存顶点之间的距离// 用10000表示距离无限大,不能连通int[][] weights = 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}};// 创建Graph对象Graph graph = new Graph(vertexNum);graph.addData2Graph(vertexs, weights);// 输出weightsgraph.showWeights();// 创建MinTree对象MinTree minTree = new MinTree();// 测试普利姆算法minTree.prim(graph, 1);}}// 图
class Graph {// 顶点个数int vertexNum;// 顶点集合char[] vertexs;// N个顶点形成的N * N二维数组,用来保存顶点之间的距离int[][] weights;// 进行初始化,但并未向数组保存值public Graph(int vertexNum) {this.vertexNum = vertexNum;this.vertexs = new char[vertexNum];this.weights = new int[vertexNum][vertexNum];}// 向图的数组保存值public void addData2Graph(char[] vertexs, int[][] weights) {for (int i = 0; i < this.vertexNum; i++) {this.vertexs[i] = vertexs[i];for (int j = 0; j < this.vertexNum; j++) {this.weights[i][j] = weights[i][j];}}}// 显示图的二维数组,即显示顶点之间的距离public void showWeights() {for (int[] line : this.weights) {System.out.println(Arrays.toString(line));}}
}// 创建最小生成树
class MinTree {// prim算法实现,生成最小生成树// vertexIndex表示顶点在vertexs的indexpublic void prim(Graph graph, int vertexIndex) {// 用来标记顶点是否被访问过。初始化都是未访问的0int[] visited = new int[graph.vertexNum];for (int i = 0; i < visited.length; i++) {visited[i] = 0;}// 当前这个结点标记为已访问visited[vertexIndex] = 1;// 临时的已访问的顶点index,和临时的未访问的顶点indexint tmpVisitedVertexIndex = -1;int tmpNotVisitedVertexIndex = -1;// 初始化minWeight为一个大数,在遍历过程中,会被赋予较小的权重值int minWeight = 10000;// 每一次遍历,都能找到一个满足条件的顶点,和一条满足条件的边for (int k = 1; k < graph.vertexNum; k++) {// 进行双层for循环处理for (int i = 0; i < graph.vertexNum; i++) {for (int j = 0; j < graph.vertexNum; j++) {// 第一层for循环表示已访问的顶点, 第二层for循环表示未访问的顶点// 如果当前边的权重值,比minWeight还小,则找到了一条更优的边if (visited[i] == 1 && visited[j] == 0 && graph.weights[i][j] < minWeight) {minWeight = graph.weights[i][j];// 更优的边的两个顶点的indextmpVisitedVertexIndex = i;tmpNotVisitedVertexIndex = j;}}}// 遍历完成,就会找到一条权重值最小的边System.out.println("找到的边<" + graph.vertexs[tmpVisitedVertexIndex] + " -> " + graph.vertexs[tmpNotVisitedVertexIndex] + ">, 权重值为: " + minWeight);// 将找到的未访问的顶点,标记为已访问visited[tmpNotVisitedVertexIndex] = 1;// 再次将minWeight重置minWeight = 10000;}}
}

运行程序,结果如下:

[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]
找到的边<B -> G>, 权重值为: 3
找到的边<G -> A>, 权重值为: 2
找到的边<G -> E>, 权重值为: 4
找到的边<E -> F>, 权重值为: 5
找到的边<F -> D>, 权重值为: 4
找到的边<A -> C>, 权重值为: 7

【数据结构与算法】普里姆算法的介绍和修路问题程序实现相关推荐

  1. 数据结构实验-图-普里姆算法、克鲁斯科尔算法

    数据结构实验-图-普里姆算法.克鲁斯科尔算法 (实验)自定义存储结构,并设计程序完成如下功能: ①创建图:创建带权无向图. ②普里姆算法:采用普里姆算法依次输出最小生成树中各条边. ③克鲁斯科尔算法: ...

  2. 用c语言描述普里姆算法和克鲁斯卡尔算法,克鲁斯卡尔算法+普里姆算法 详解

    克鲁斯卡尔算法: [1]克鲁斯卡尔算法 普里姆算法是以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树. 克鲁斯卡尔算法是直接以边为目标去构建. 因为权值是在边上,直接去找最小权值的边来构建生 ...

  3. 算法 - 普里姆算法(修路问题求解)

    从A开始,A作为定点,找到与A相连并且未被处理(不在顶点集合中)的进行处理,找到权值最小的并加入集合,A-C[7].A-G[2].A-B[5],最小的是A-G[2],所以把G加入集合,这里是有A-G的 ...

  4. 最小生成树(克鲁斯卡尔算法 普里姆算法)

    最小生成树是处理图结构中,简化图的算法:即删除一些边使得图得以简化,但应保证图中任意点都是相连通的.形成的最小生成树应该使得从顶点遍历时走过边的权值和最小.(有n个节点,则最小生成树的边数应为n-1) ...

  5. 最小生成树:克鲁斯卡尔算法+普里姆算法

    目录 一.最小生成树 二.克鲁斯卡尔算法 1.思路 2.示例 3.C语言代码 三.普里姆算法 1.思路 2.C语言代码 一.最小生成树 一棵最小生成树需要满足哪些条件呢? 不存在回路 对于具有n个顶点 ...

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

    普里姆算法 假设G=(V,E)是一个具有n个顶点的连通网,T=(U,TE)是G的最小生成树,其中U是T的顶点集,TE是T的边集,U和TE的初始值为空.算法过程: 首先从V中任取一个顶点(假定v1),将 ...

  7. 【数据结构】最小生成树(Prim算法,普里姆算法,普利姆)、最短路径(Dijkstra算法,迪杰斯特拉算法,单源最短路径)

    文章目录 前置问题 问题解答 一.基础概念:最小生成树的定义和性质 (1)最小生成树(Minimal Spanning Tree)的定义 (2)最小生成树(MST)的性质 二.如何利用MST性质寻找最 ...

  8. 学渣都能看懂的-最小生成树Prim算法(普里姆算法)

    最小生成树问题:要将图中的n个点连通,即任意两点之间都存在路径.要使连通图中各边的权值之和最小. 例: 最小生成树所要掌握的点: ·求出最小生成树权值之和 ·保存最小生成树的各边 使各边权值之和最短需 ...

  9. 大话数据结构-普里姆算法(Prim)和克鲁斯卡尔算法(Kruskal)

    5 最小生成树   构造连通网的最小代价生成树称为最小生成树,即Minimum Cost Spanning Tree,最小生成树通常是基于无向网/有向网构造的.   找连通网的最小生成树,经典的有两种 ...

  10. 我所知道的十大常用算法之普里姆算法(最小生成树)

    前言需求 今天我们学习的是普里姆算法,我们还是从一个场景里引入看看 有7个村庄(A, B, C, D, E, F, G) ,现在需要修路把7个村庄连通 1.各个村庄的距离用边线表示(权) ,比如 A ...

最新文章

  1. 洛谷P4762: [CERC2014]Virus synthesis(PAM)
  2. 【渝粤题库】国家开放大学2021春2223物业管理财税基础题目
  3. 2021年陕西高考成绩单招查询时间,2021年陕西高考录取结果什么时候出来,查询时间一览表...
  4. 王炸!Waymo正式官宣无人车出行平台,瑟瑟发抖的不止Uber
  5. AngularJS的学习--ng-show/ng-hide/ng-if和ng-switch
  6. systemctl和正则表达式
  7. UML 简单易懂 教程
  8. 有什么软件可以测试U盘性能,最新版本:U盘性能检查测试软件简介
  9. 树莓派Ubuntu18.04使用及联网
  10. mysql gtid dump_MySQL之mysqldump备份的--set-gtid-purged参数
  11. 小觅双目相机如何使用_小觅双目相机测试
  12. php版本大屏幕,PHP现场抽奖大屏幕互动系统
  13. 数据科学家也良莠不齐 蹩脚数据科学家的10个迹象
  14. Python第三方库matplotlib(2D绘图库)入门与进阶
  15. 【CareerCup】 Linked Lists—Q2.5
  16. 互联网公司招聘--阿里巴巴--游戏运营--2015年笔试题
  17. 《Netty实战-写一个RPC应用》
  18. PDF文件打开密码忘记了
  19. 怎么看电影《穆赫兰道》?
  20. Mac电脑app store登录不了的问题

热门文章

  1. 今天为什么仍必须进行门级仿真(GLS)详细讲解
  2. js中时间戳的各种用法
  3. 【akka】Akka源码分析-Event Bus
  4. 聊斋志异 - 善恶篇,诡异录,苍穹斗
  5. 查看Android手机上的CellID等信息
  6. google检索技巧-从菜鸟到黑客
  7. 不看绝对血亏!docker镜像下载不下来
  8. c语言程序设计 a,C语言程序设计试题A
  9. 中国土地利用现状遥感监测数据(1985-2020年)
  10. 计算机主机的拆卸的注意事项,如何进行电脑主机除尘及板卡维护