最小生成树Prim普里姆算法理论



最小生成树的应用场景:顶点代表城市的话,比如说修路,架设电线,网络,怎么让这几个城市连起来,而且花费是最小的,成本最低,权值是最小的,但是不允许形成环路。

第一步的U,V集合类似于迪杰斯特拉的S和U集合。
U集合放的是已经选好的点,V集合放的是未选好的点

首先选择权值最小的节点。我们选择从A开始,A-B,A-C,A-D中,权值最小的边是A-C,加入到最小生成树当中。

把C加入到U集合中,也就是选进去了。然后把剩余顶点(BDEF)的权值都和C算一下,如果谁和C的权值,比它原本和A的权值更小,就更新一下。
也就是说,B原来到A的权值是6,现在新选择了C这个节点,加入到U集合当中了,我们先计算一下C-B的权值,C-B是5,B-C的权值是5,小于B-A的权值6,所以把B这个权值更新为到C这个顶点的5,
D原来到A的权值是5,现在D-C的权值也是5,就不用更新了
E原来到A是无穷大,现在D到C是6,所以把E的权值更新一下
F原来到A是无穷大,现在F到C是4,所以把F的权值更新一下
如下图所示:

然后接着,因为选择AC到U集合中了,然后在BDEF中找权值最小的节点,就是F,然后把C-F连起来,然后把F添加到U集合中,看跟F的权值是否更小,就要更新一下V中的节点(BDE)的权值。

然后看BE谁的权值最小,连哪个节点,B的权值最小,把B添加到U结合集合中,然后更新一下权值
最后把E添加到U集合中
然后更新一下权值

OK了!!!

最小生成树Prim普里姆算法代码实现


在A中添加B和B的权值:

package com.fixbug;import java.util.LinkedList;
import java.util.Scanner;/*** 描述: 最小生成树 - 普里姆算法代码实现 - 加点法** @Author shilei*/
public class Prim {/*** 邻接表节点的类型*/static class Entry{int id;//表示顶点的idint cost;//表示到达id顶点的权值public Entry(int id, int cost) {//构造函数 this.id = id;this.cost = cost;}}/*** 邻接表数组元素类型*/static class Vertic{char name;//顶点的名字 LinkedList<Entry> adjlist;//链表 public Vertic(char name) {//构造函数 this.name = name;this.adjlist = new LinkedList<>();}}public static void main(String[] args) {//定义顶点信息char[] vertics = {'A', 'B', 'C', 'D', 'E', 'F'};int number = vertics.length;//定义顶点的个数 //手动输入边的信息,建立邻接表结构Scanner in = new Scanner(System.in);Vertic[] verticList = new Vertic[number];//邻接表 for (int i = 0; i < verticList.length; i++) {verticList[i] = new Vertic(vertics[i]);//添加顶点的名字进去 }//输入边的信息System.out.print("输入边的个数:");int edgeNumber = in.nextInt();in.nextLine();//把读完整数,缓冲区剩余的回车读掉System.out.println("输入边的信息:");//A B 6int minCost = Integer.MAX_VALUE;int minCostIndex = 0;//记录权值最小的顶点的下标for (int i = 0; i < edgeNumber; i++) {String line = in.nextLine();String[] infos = line.trim().split(" ");//通过空格分割一下 //获取起点和终点的编号int start = 0, end = 0;for (int j = 0; j < vertics.length; j++) {if(vertics[j] == infos[0].charAt(0)){start = j;} else if(vertics[j] == infos[1].charAt(0)){end = j;}}//获取输入的权值int cost = Integer.parseInt(infos[2]);if(minCost > cost){minCost = cost;minCostIndex = start;//记录权值最小的顶点 }//把信息添加到邻接表当中 start - end 的 cost  end - start的 costverticList[start].adjlist.add(new Entry(end, cost));verticList[end].adjlist.add(new Entry(start, cost));}//上面创建好了邻接表结构,下面开始普里姆算法代码实现final int INF = Integer.MAX_VALUE;Entry[] cost = new Entry[number];//顶点的cost boolean[] use = new boolean[number];//表示U和V集合 //U放选择好的顶点   V待选择的顶点use[minCostIndex] = true; //表示把minCostIndex选入u集合for (int i = 0; i < cost.length; i++) {cost[i] = new Entry(minCostIndex, INF);//刚开始计算的是离顶点A的,权值都初始化为INF }LinkedList<Entry> list = verticList[minCostIndex].adjlist;//遍历A的链表,看到有谁,就把谁的权值改过来 for (int i = 0; i < list.size(); i++) {cost[list.get(i).id].cost = list.get(i).cost;}//开始继续搜索后面的顶点for (int i = 1; i < number; i++) {//找到权值最小的顶点int k = -1;int min = INF;for (int j = 0; j < cost.length; j++) {if(!use[j] && cost[j].cost < min){//未选择的数组中找 min = cost[j].cost;k = j;}}//选择了第k各顶点use[k] = true;//打印最小生成树的边System.out.println(verticList[cost[k].id].name + " -> " +verticList[k].name);//把第k各节点新添加到u集合当中,更新剩下的顶点的权值信息了for (int j = 0; j < cost.length; j++) {if(!use[j]){//计算j顶点和k顶点的权值,是否比j之前记录的到某个顶点的权值更小,然后更新顶点权值list = verticList[k].adjlist;for (Entry entry : list) {if(entry.id == j){if(entry.cost < cost[j].cost){cost[j].cost = entry.cost;cost[j].id = k;}break;}}}}}}
}

C++代码

#include <iostream>
#include <vector>
using namespace std;using uint = unsigned int;
const uint INF = INT_MAX;int main()
{vector<vector<uint>> graph ={{0, 6, 3, INF, INF, INF},{6, 0, 2, 5, INF, INF},{3, 2, 0, 3, 4, INF},{INF, 5, 3, 0, 2, 3},{INF, INF, 4, 2, 0, 5},{INF, INF, INF, 3, 5, 0},};// 一次把每一个顶点加入for (int k = 0; k < graph.size(); k++){// 都需要遍历邻接矩阵for (int i = 0; i < graph.size(); i++){for (int j = 0; j < graph.size(); j++){graph[i][j] = min(graph[i][j], graph[i][k]+graph[k][j]);}}}for (auto line : graph){for (auto dis : line){cout << dis << " ";}cout << endl;}// cout << graph[start][end] << endl;
}

644-最小生成树Prim普里姆算法相关推荐

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

    一:最小生成树 (一)定义 我们把构造连通网的最小代价生成树称为最小生成树或给定一个带权的无向连通图,如何选取一棵生成树,使树上所有边上权的总和为最小,这叫最小生成树. (二)什么是最小生成树? 1. ...

  2. JavaScript实现prim普里姆算法(附完整源码)

    JavaScript实现prim普里姆算法(附完整源码) Comparator.js完整源代码 Heap.js完整源代码 MinHeap.js完整源代码 PriorityQueue.js完整源代码 G ...

  3. 最小生成树之普里姆算法

    为了能够讲明白这个算法,我们先构造网图的邻接矩阵,如图7-6-3的右图所示. 也就是说,现在我们已经有了一个存储结构为MGraph的MG(见<邻接矩阵创建图>).MG有9个顶点,它的二维数 ...

  4. 最小生成树(普里姆算法)

    关于什么是Prim(普里姆算法)? 在实际生活中,我们常常碰到类似这种一类问题:如果要在n个城市之间建立通信联络网, 则连通n个城市仅仅须要n-1条线路.这时.我们须要考虑这样一个问题.怎样在最节省经 ...

  5. 最小生成树之普里姆算法(Prim算法)

    图论中的一种算法,可在加权连通图里搜索最小生成树.由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小. 算法描述 1).输入:一个加权连通图,其中顶点集合为 ...

  6. (浙大-19-夏-数据结构)Prim(普里姆算法)和Kruskal(克鲁斯卡尔算法)最小生成树

    Prim最小生成树算法(贪心算法) 最小生成树的性质: 一棵树 没有回路 n 个顶点含有 n - 1 条边 生成树 所有顶点都在里面 n - 1 条边都在图中 边的权重最小 在生成树的图中任意加一条边 ...

  7. 【数据结构和算法】图论—最小生成树,普里姆算法(Prim)

  8. Prim 普里姆算法(邻接矩阵)C语言版

    Prim算法的思维路线较为简单,百度基本都能看懂.但是编程还是有点难的. 整个围绕两个东西转,一个lowcost数组,一个adjvex数组,前者是用来保存当前生成树到其它顶点的权值的. 比如这个图,假 ...

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

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

最新文章

  1. linux系统中find怎么用,linux系统中‘find’的详细用法
  2. Delphi 2010 secondsBetween Bug
  3. 阿里开源了一项自研核心技术 Pouch!
  4. Gogs-Windows Server下搭建Git服务器
  5. iOS Safari 中click点击事件失效的解决办法
  6. java 发送邮件_SpringBoot 2.1.5发送验证码邮件
  7. iOS 如何使用 Block
  8. PHP程序员测试题及答案
  9. 一例Ext4文件系统fsck后损坏的修复过程
  10. React动画实现原理
  11. c3p0数据库连接池不能取到连接
  12. 【STM32F042】使用NTC热敏电阻实现温度测量
  13. ubuntu 挂载 windows 分区
  14. opencv 表格识别之表格的提取(一)
  15. c#阿里CSB接口对接--
  16. 校园实践-校园二手交易项目组-墨刀原型
  17. 单片机实例1——闪烁灯(硬件电路图+汇编程序+C语言程序)
  18. JAVA:使用华为云存储OBS处理文件
  19. 计算机管理员已禁用了teredo,Win7提示设备管理器中出现叹号设备“Teredo tunneling pseudo-interface”...
  20. 如何保持较长时间的专注

热门文章

  1. 用手机查询北京实时路况
  2. android获取图片背景色,GlidePalette获取图片背景色
  3. 华为鸿蒙路线图,华为鸿蒙 华为鸿蒙OS路线图公布:1.0版首发于智慧屏、2.0...
  4. 安装htttp协议库(axios)
  5. 易基因技术推介|全基因组重亚硫酸盐甲基化测序(WGBS)
  6. unity导入jslib问题
  7. ARM CMSIS DAP源码分析
  8. 【Linux】《Linux命令行与shell脚本编程大全 (第4版) 》笔记-Chapter6-Linux 环境变量
  9. Plural Form of Nouns
  10. wxpython绘制雷达图_Python 手绘风格可视化神包:cutecharts