最小生成树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. hive金额怎么转换千位分隔符_金额字段加千位分隔符方法
  2. 修改类名后依旧按照原先的类名进行加载
  3. call() , apply() ,bind()的用法
  4. Linux远程管理协议(RFB、RDP、Telnet和SSH)
  5. 计算机专业外语英译汉,信科计算机专业英语英译汉
  6. 总结一下安装linux系统经验-版本选择-安装ubuntu
  7. DTNSim.java注释摘要(学习性质,有错漏的可能,红色为不明确部分)
  8. [转]SQLite内存数据库
  9. Linux下Oracle中sqlplus上下键乱码问题
  10. JAVA删除文件或者文件夹
  11. python 流程结构练习
  12. Excel——批量填充有序序列、填充字母序列、自定义序列排序
  13. 从存活了1441年的企业,我们能学到什么?
  14. 千万并发,阿里淘宝的 14 次架构演进之路!
  15. uniapp移除原生导航栏后页面与手机状态栏重叠问题
  16. Python统计学01——数据可视化
  17. I/O控制方式——轮询,中断,DMA,通道
  18. 0基础如何用几分钟学会视频剪辑
  19. 电动汽车充电桩中的漏电保护应用分析 RCD的分类和选型
  20. python人工智能面试题爱奇艺面试题_【爱奇艺Python面试】爱奇艺大数据面试 python-看准网...

热门文章

  1. 【UE4 第一人称射击游戏】18-添加角色换弹时的动作
  2. 计算机存储单位转换(KB MB GB TB PB EB ZB)
  3. 10.模型层与ORM
  4. 在Android用vulkan完成蓝绿幕扣像
  5. 静态时序分析简明教程(五)]生成时钟的sdc约束方法
  6. linux7 rpmdb 修复,RPM DB 修复
  7. kali如何开放端口
  8. 如何对网站用户进行实名认证
  9. ITEXT 页眉页脚页码三件套
  10. 原生php开发新闻发布系统源码