Prim算法是另一种生成图的最小生成树的算法,这里简单说一下Prim算法和Kruskal算法的在实现方面的区别:

1、Kruskal算法在生成最小生成树的过程中产生的是森林,Prim算法在执行过程中始终都是一棵树;

2、Kruskal和Prim实现上的最大区别是Kruskal不需要搜索每个顶点的邻接节点,而Prim中需要,所以Prim图构建时需要利用邻接链表进行构建,Kruskal不用!

上面第二点边提出了Prim算法实现过程中特点,就是构建图的过程中需要邻接链表表示加权无向图!
Prim算法中构建的加权无向图的邻接链表如下图所示:

根据上图可知,即是将权重作为邻接链表中的每个节点对象的属性。
比如上面第一个邻接链表表示的便是:边v1–>v8:权重为8;边v1–>v2:权重为4


一、Prim算法需要的数据结构知识

1、图顶点对象及其属性定义:

public class VertexWG {String verName;  //名称int weight;  //权重double key;  //key是键顶点v与树中某一顶点相连的边中最小权值VertexWG parent;  //父对象VertexWG nextNode;  //下一个节点对象
}

2、最小堆:最小堆的顶点对象是Vertex,排序是通过Vertex的属vertex.key进行排序的
对于vertex的key属性要明确:vertex.key是所有将v与树中某一顶点相连的边中最小权值,按约定如果不存在这样的边,则vertex.key=∞


二、Prim算法实现具体思路

首先给出伪代码:

伪代码1~5行:对每个顶点对象进行初始化,并初始化优先级队列Q,是其包含所有初始化的节点;
伪代码6~11行:首先只要优先级队列不为空,则while循环一直继续!从Q中选出v.key最小的顶点,然后遍历它的每一个邻接节点,当其邻接节点满足两个条件:
1、该节点v仍在Q中
2、该节点v满足w(u,v)< v.key
满足上面条件边更新节点的key值信息和parent信息。知道while循环结束!


三、Prim算法java实现

1、Graph对象类

public class GraphWG {VertexWG[] vertexArray=new VertexWG[100];int verNum=0;int edgeNum=0;
}

2、Vertex对象类

public class VertexWG {String verName;int weight;double key;VertexWG parent;VertexWG nextNode;
}

3、创建图

import java.util.Scanner;public class CreateWG {double infinity=10.0/0.0;/*** 根据用户输入的string类型的顶点返回该顶点* @param graph 图* @param str 输入数据* @return返回一个顶点*/public static VertexWG getVertex(GraphWG graph,String str){for(int i=0;i<graph.verNum;i++){if(graph.vertexArray[i].verName.equals(str)){return graph.vertexArray[i];}}return null;}/*** 初始化一个无向带权图,并且每个顶点包含parent域和key域* @param graph 生成的图*/public void initialWg(GraphWG graph){@SuppressWarnings("resource")Scanner scan=new Scanner(System.in);System.out.println("请输入顶点数和边数:");graph.verNum=scan.nextInt();graph.edgeNum=scan.nextInt();System.out.println("请依次输入定点名称:");for(int i=0;i<graph.verNum;i++){VertexWG vertex=new VertexWG();String name=scan.next();vertex.verName=name;vertex.key=infinity;vertex.parent=null;vertex.nextNode=null;graph.vertexArray[i]=vertex;}System.out.println("请依次输入图的便边:");for(int i=0;i<graph.edgeNum;i++){String preV=scan.next();String folV=scan.next();int weight=scan.nextInt();VertexWG v1=getVertex(graph,preV);if(v1==null)System.out.println("输入边存在图中没有的顶点!");VertexWG v2=new VertexWG();v2.verName=folV;v2.weight=weight;v2.nextNode=v1.nextNode;v1.nextNode=v2;VertexWG reV2=getVertex(graph,folV);if(reV2==null)System.out.println("输入边存在图中没有的顶点!");VertexWG reV1=new VertexWG();reV1.verName=preV;reV1.weight=weight;reV1.nextNode=reV2.nextNode;reV2.nextNode=reV1;}}public void outputWG(GraphWG graph){System.out.println("输出加权图的邻接链表:");for(int i=0;i<graph.verNum;i++){VertexWG vertex=graph.vertexArray[i];System.out.print(vertex.verName);VertexWG current=vertex.nextNode;while(current!=null){System.out.print("-->"+current.verName+"("+current.weight+")");current=current.nextNode;}System.out.println();}}
}

4、Prim算法核心实现类

import java.util.Scanner;
/*** <pre>* 1>.Kruskal算法实现利用EdgeNode数据结构*    Kruskal和Prim实现上的最大区别是Kruskal不需要搜索每个顶点的邻接节点*    而Prim中需要,所以Prim图构建时需要利用邻接链表进行构建,Kruskal不用!* 2>.使用邻接链表构建无向加权图,prim构建MST过程中始终只有一棵树* 3>.每个vertex对象包含属性:parent、key、verName、weight、nextNode* 4>.这里最小堆minHeap节点对象是Vertex,构建是通过vertex.key构建的* 5>.root节点随机选取,通过遍历每个选出节点的邻接节点,然后不断更新每个节点的key值 !</pre>* @author King* */
public class Prim {//  下面全局变量对于程序十分重要int currentSize=0;int maxSize=0;VertexWG[] minHeap=new VertexWG[20];/*** 通过weight构建以EdgeNode为节点的最小堆* @param edgeNode为带权的边集*/public void createMinHeap(VertexWG[] verArray){currentSize=verArray.length;maxSize=minHeap.length;if(currentSize>=maxSize){maxSize*=2;minHeap=new VertexWG[maxSize];}for(int i=0;i<currentSize;i++)minHeap[i+1]=verArray[i];double y;int c;for(int i=currentSize/2;i>=1;i--){VertexWG ver=minHeap[i];y=ver.key;c=2*i;while(c<=currentSize){if(c<currentSize && minHeap[c].key>minHeap[c+1].key)c++;if(minHeap[c].key>=y)break;minHeap[c/2]=minHeap[c];c=c*2;}minHeap[c/2]=ver;}}/*** 最小堆删除两种思路,一种和前面一样,就是一直跟踪放在根节点的那个最后一个节点最终插入的位置* 另一种思路便是每一次完成完整的交换然后下一一层在进行同样处理*/public VertexWG deleteMinHeap(){if(currentSize<1)System.out.println("堆已经为空!无法执行删除");VertexWG ver=minHeap[1];minHeap[1]=minHeap[currentSize];currentSize-=1;int c=2,j=1;VertexWG ver1=minHeap[currentSize+1];while(c<=currentSize){if(c<currentSize && minHeap[c].key>minHeap[c+1].key)c++;if(ver1.key<=minHeap[c].key)break;minHeap[j]=minHeap[c];j=c;c=c*2;}minHeap[j]=ver1;return ver;}/*** 从这里返回minHeap中的顶点对象* @param name 定点的名字* @return返回minHeap中的一个顶点对象*/public VertexWG getHeapVertex(String name){for(int i=1;i<=currentSize;i++){if(minHeap[i].verName.equals(name))return minHeap[i];}return null;}/*** MST的Prim算法具体实现函数* @param graph 图*/public void primSpanningTree(GraphWG graph){System.out.println("请输入root节点:");@SuppressWarnings("resource")Scanner scan=new Scanner(System.in);String root=scan.next();VertexWG verRoot=CreateWG.getVertex(graph,root);verRoot.key=0;VertexWG[] verArray=new VertexWG[graph.verNum];for(int i=0;i<graph.verNum;i++){verArray[i]=graph.vertexArray[i];}createMinHeap(verArray);System.out.println("利用prim算法依次加入到MST中的顶点顺序为:");while(currentSize>=1){
//          需要考虑的一个问题便是minHeap中的对象和graph.vertexArray中的是否是同一个对象>>答案:不是同一个对象
//          minHeaph中的对象已经是新产生的对象了
//          这里注意一下u这个对象,u自然是minHeap中的对象VertexWG[] vArray=new VertexWG[currentSize];for(int i=0;i<currentSize;i++){vArray[i]=minHeap[i+1];}
//          这里需要注意,每次删除节点更新完key值之后,需要利用新的key值重新构建最小堆createMinHeap(vArray);VertexWG u=deleteMinHeap();System.out.println(">."+u.verName);VertexWG current=u.nextNode;
//          注意下面while循环中的两个不同的顶点对象:currentNow、currentwhile(current!=null){VertexWG currentNow=getHeapVertex(current.verName);if(currentNow!=null && current.weight<currentNow.key){currentNow.parent=u;currentNow.key=current.weight;}current=current.nextNode;}}}public static void main(String[] args) {GraphWG graph=new GraphWG();CreateWG createWG=new CreateWG();createWG.initialWg(graph);createWG.outputWG(graph);Prim prim=new Prim();prim.primSpanningTree(graph);}
}

测试所有的无向加权图如下所示:

测试输入数据截图(部分):

测试结果截图:

这里大家可以看出Prim算法的根节点是自己随机选取的,不影响最小生成树的形成!

有什么问题欢迎大家指正,谢谢!!

Prim算法实现最小生成树MST(java)相关推荐

  1. Prim算法实现最小生成树(Java)

    最小生成树包含n个顶点和(n-1)条边,并且边的权重最小.Prim算法的思想是:由一颗小树慢慢长大,首先分为两个顶点集合,最小生成树的顶点集合A,和不在生成树中的顶点集合B,每次从B中找一个顶点v,使 ...

  2. 三十七、Prim算法--求解最小生成树

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

  3. prim算法 求最小生成树

    最小生成树Prim算法理解 标签: Prim算法理解最小生成树Prim 2014-08-16 18:49 18482人阅读 评论(5) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转载. ...

  4. 小黑算法成长日记18:基于Prim算法的最小生成树

    import math nodes = ['A','B','C','D','E','F'] # 结点数组 vecs = [[0,1,6],[0,2,1],[0,3,5],[1,0,6],[1,2,5] ...

  5. Prim算法实现最小生成树

    Prim算法实现最小生成树 1.最小生成树是什么 2.最小生成树的用途 3.Prim算法描述 4.Prim算法演示最小生成树过程 5.Prim算法实现 END 1.最小生成树是什么 对连通图进行遍历, ...

  6. 1分钟解决Prim算法构造最小生成树

    数据结构期末上分必备 前言:Prim 算法构造最小生成树!!!跟着画一遍就会了!!! Kruskal 请移步 kruskal 题目 设有如下图所示的无向连通图,从顶点A出发,使用 Prim 算法构造最 ...

  7. Java 版 Prim 算法求最小生成树

    最小生成树: 一个具有n个顶点的加权的无相连通图,用n-1条边连接这n个顶点,并且使得连接之后的所有边的权值之和最小的树. Prim算法:先以一个结点作为最小生成树的第一个结点,然后以迭代的方式找出与 ...

  8. prim算法_最小生成树(Kruskal和Prim算法)

    文章和资源同步更新至微信公众号:算法工程师之路 8月份会开启每日算法题系列,值得期待哦 上一篇文章,我们讲了图的创建和遍历,其中遍历的算法主要有BFS(广度优先算法)和DFS(深度优先算法)两种,并且 ...

  9. Prim算法解决最小生成树 (解决修路问题)

    一.什么是Prim算法  普里姆算法查找最小生成树的过程,采用了贪心算法的思想.对于包含 N 个顶点的连通网,普里姆算法每次从连通网中找出一个权值最小的边,这样的操作重复 N-1 次,由 N-1 条权 ...

  10. C语言实现Prim算法 —构建最小生成树

    目录 介绍Prim算法前的相关概念 一.Prim算法的思想 二.1.利用图形详细解释Prim算法的思想 Prim算法思想介绍 ​ 二.2利用图形又又解释Prim算法的思想 三.用图示结合代码中重要量进 ...

最新文章

  1. em算法怎么对应原有分类_机器学习系列之EM算法
  2. 雅虎网站页面性能优化的34条黄金守则 收藏
  3. vs2015如何连接oracle,VS2015中C#连接Oracle数据库
  4. docker run
  5. python 前端开发_python和前端开发怎么抉择?
  6. 英特尔®以太网700系列的动态设备个性化
  7. 使用C语言快速统计fastq文件q20、q30、GC含量
  8. 实用小技巧 利用Python一秒将全部中文名转为拼音
  9. 库克说他在上大学时学会了编程,你呢?
  10. STM32CubeIDE 介绍及安装
  11. PHP中级工程师面试题
  12. iOS解决UITableView头部和底部出现空白间隙的折腾
  13. 2022年高处安装、维护、拆除操作证考试题库及答案
  14. GeneXus开发工具
  15. ABAQUS 建模及分析流程(一)
  16. GIS - 底图,怎么做怎么选择
  17. 头发护理 -- 生发养发
  18. shell命令之find
  19. IntelliJ IDEA 可以使用中文了
  20. python关键词_Python批量挖掘百度凤巢关键词

热门文章

  1. Codeforces 679A Bear and Prime 100
  2. MplusAutomation包的使用 二
  3. ConurrentHashMap和Hashtable的区别
  4. VS2010与.NET4系列 13. ASP.NET 4 SEO 改进
  5. scrum角色及其职责介绍
  6. Lua概念定义及相关资料
  7. Eclipse 无法打开Console,show view无效
  8. 如何让百度快速收录自己的wordpress网站
  9. HNUCM 1325:fps游戏
  10. 2.自编码器(去噪自编码器,DAE)