Prim算法最小生成树Java超详解
算法简介
算法流程
具体实现
Code
Input
Output
使用优先队列实现
API说明
Code
Input
Output
算法简介
Prim算法计算最小生成树,它的每一步都会为一颗生长树添加一条边。一开始这棵树只有一个顶点,然后我们会向它逐步添加边,每次总是将下一条连接树中的顶点与不在树中的顶点且权重最小的边加入到树中。
算法流程
原图:
从顶点0开始建树:
下面我们为了更直观明了的看出已放入树中的顶点的minCost值不被使用,把minCost值修改为红色:
使用Prim算法产生的最小生成树:
具体实现
Code
import java.util.*;
import java.io.*;public class prim {public static final int INF=1000;//定义一个无限距离,当两个顶点之间不存在连接且无权值设置为INFpublic static int V;//顶点个数public static int cost[][];//cost[v][u]表示从顶点v到顶点u的权值public static int minCost[];//从顶点集合出发的边到每个顶点的最小权值public static boolean used[];//顶点是否已经放入树中public static void main(String[] args) {Scanner in = new Scanner(new BufferedInputStream(System.in));while (in.hasNext()) {V=in.nextInt();System.out.println("顶点有:"+V+"个");//顶点从0到V-1cost=new int[V][V];used=new boolean[V];minCost=new int[V];//初始化for (int i = 0; i < V; i++) {minCost[i]=INF;used[i]=false;Arrays.fill(cost[i],INF);}//顶点之间的边赋值 输入为0 0 0 时退出while (true){int v1=in.nextInt();//顶点1int v2=in.nextInt();//顶点2int c=in.nextInt();//顶点之间权值if(v1==0&&v2 == 0&&c == 0){System.out.println("结束输入");break;}cost[v1][v2]=c;cost[v2][v1]=c;System.out.println("顶点"+v1+"->顶点"+v2+"权值为: "+c);}//以0为起始点开始建树minCost[0]=0;int res=0;while (true){int v=-1;for (int i = 0; i < V; i++) {//寻找没有被放入树中且权值最小的顶点if(!used[i]&&(v==-1||minCost[i]<minCost[v])){v=i;}}if (v==-1){System.out.println("建树完成");break;}//最小生成树已经建立完成,所有顶点都放入树中,退出used[v]=true;//把v这个顶点加入树中System.out.println("顶点"+v+"已被使用");res+=minCost[v];//把边的长度加入到结果中for (int i = 0; i < V; i++) {minCost[i]=Math.min(minCost[i],cost[v][i] );//更新放入树中的最小权值}}System.out.println("最小生成树的权值和为"+res);}}
}
Input
7
0 1 2
0 3 10
1 6 1
1 2 3
1 4 7
2 4 1
3 4 5
4 5 8
2 5 5
0 0 0
Output
顶点有:7个
顶点0->顶点1权值为: 2
顶点0->顶点3权值为: 10
顶点1->顶点6权值为: 1
顶点1->顶点2权值为: 3
顶点1->顶点4权值为: 7
顶点2->顶点4权值为: 1
顶点3->顶点4权值为: 5
顶点4->顶点5权值为: 8
顶点2->顶点5权值为: 5结束输入
顶点0已被使用
顶点1已被使用
顶点6已被使用
顶点2已被使用
顶点4已被使用
顶点3已被使用
顶点5已被使用
建树完成
最小生成树的权值和为17
使用优先队列实现
通过不断搜索要放入树中顶点相连的顶点权值,不断更新可放入的顶点权重,也可以使用优先队列来实现,为了快速构建,这里使用了算法第四版的数据结构:
首先导入jar包:
jar包下载
提取码:0068
API说明
数据结构API简要说明:
伪代码:
Edge: ->边int v ->一个顶点int w ->另一个顶点double weight ->权重int weight() ->获取边权重int either() ->获取一个顶点int other(int v) ->获取另一个顶点
EdgeWeightedGraph ->带权无向图final int V ->顶点总数int E ->边的总数Bag<Edge>[] adj->邻接表 此处Bag类似于Listvoid addEdge(Edge e) ->添加边
具体数据结构实现可通过导包,将数据结构类写出,右键点击转到->实现,即可查看:
这里我们不关心怎样方法实现,只要会调用具体方法,只关心算法本身就好,具体实现可以用不同的数据结构来书写。
Code
import edu.princeton.cs.algs4.Edge;
import edu.princeton.cs.algs4.EdgeWeightedGraph;
import edu.princeton.cs.algs4.IndexMinPQ;import java.util.*;
import java.io.*;public class Prim_MST {public static final int INF=1000;//定义一个无限距离,当两个顶点之间不存在连接且无权值设置为INFpublic static Edge[]edgeTo;//距离树最近的边public static int[]distTo;//distTo[w]=edgeTo[w].weight;public static boolean[]used;//顶点在树中设置为trueprivate static IndexMinPQ<Integer>pq;//有效横切边 来获取最小权值花费的顶点 这里也可以使用SortedMap设置一个比较器来实现public static EdgeWeightedGraph G;//权重图public static void main(String[] args) {Scanner in = new Scanner(new BufferedInputStream(System.in));while (in.hasNext()) {//输入数据int V=in.nextInt();//开始创建图System.out.println("建造一个有"+V+"个顶点的带权无向图");G=new EdgeWeightedGraph(V);//开始添加边//顶点之间的边赋值 输入为0 0 0 时退出while (true) {int v1 = in.nextInt();//顶点1int v2 = in.nextInt();//顶点2int c = in.nextInt();//顶点之间权值if (v1 == 0 && v2 == 0 && c == 0) {System.out.println("结束输入");break;}Edge e=new Edge(v1,v2,c);G.addEdge(e);System.out.println(e.toString());}//开始创建最小生成树Prim_MST mst = new Prim_MST(G);//创建完成后打印信息int res=0;for (int i = 0; i < distTo.length; i++) {res+=distTo[i];System.out.println("最小生成树里顶点"+i+"所连接的边的权值为"+distTo[i]);}System.out.println("最小生成树权值为"+res);}}public Prim_MST(EdgeWeightedGraph G){edgeTo=new Edge[G.V()];distTo = new int[G.V()];used = new boolean[G.V()];for (int v=0;v < G.V(); v++){distTo[v]=INF;}pq=new IndexMinPQ<Integer>(G.V());distTo[0]=0;//从顶点0开始建树pq.insert(0,0);//顶点0和权值0初始化pq/*** 当所有有效横切边被加入树中,pq队列就为空**/while (!pq.isEmpty()){//将权值花费最小的顶点加入树中,同时在队列pq中删除,不去比较此顶点权值最小花费visit(G,pq.delMin());}}public static void visit(EdgeWeightedGraph G,int v){//将顶点v放入树中used[v]=true;System.out.println("顶点"+v+"已被使用");//遍历这个顶点的邻接表for (Edge e : G.adj(v)){int w=e.other(v);//取出另一个顶点if(used[w])continue;//如果已被使用就跳过说明这两顶点之间在最小生成树里不相连if(e.weight()<distTo[w]){//连接w和树的最佳边变成eedgeTo[w]=e;//如果这个边的权值小于此时distTo[w]的值更新 这里相当于minCostdistTo[w]= (int) e.weight();//因为我使用边的权值是int值,但Edge实现使用的是double,所以需要转化一下if (pq.contains(w)){//如果有效横切边存在队列里,更新值pq.changeKey(w,distTo[w]);}else {//如果不在添加进去pq.insert(w,distTo[w]);}}}}
}
Input
7
0 1 2
0 3 10
1 6 1
1 2 3
1 4 7
2 4 1
3 4 5
4 5 8
2 5 5
0 0 0
Output
建造一个有7个顶点的带权无向图
0-1 2.00000
0-3 10.00000
1-6 1.00000
1-2 3.00000
1-4 7.00000
2-4 1.00000
3-4 5.00000
4-5 8.00000
2-5 5.00000结束输入
顶点0已被使用
顶点1已被使用
顶点6已被使用
顶点2已被使用
顶点4已被使用
顶点5已被使用
顶点3已被使用
最小生成树里顶点0所连接的边的权值为0
最小生成树里顶点1所连接的边的权值为2
最小生成树里顶点2所连接的边的权值为3
最小生成树里顶点3所连接的边的权值为5
最小生成树里顶点4所连接的边的权值为1
最小生成树里顶点5所连接的边的权值为5
最小生成树里顶点6所连接的边的权值为1
最小生成树权值为17
Prim算法最小生成树Java超详解相关推荐
- java的hash算法实现_一致性Hash算法的Java实现详解
package com.baijob.commonTools; import java.util.Collection; import java.util.SortedMap; import java ...
- 内部排序算法比较(超详解)
一.题目描述 通过随机数据比较各排序算法的关键字比较次数和关键字移动次数,以 及执行时间,取得直观感受. 二.设计要求 一.需求分析 实现各排序算法,分别进行以下各组比较,并进行总结. 一.各算法在不 ...
- 希尔排序基础java代码_java 算法之希尔排序详解及实现代码
摘要:这篇Java开发技术栏目下的"java 算法之希尔排序详解及实现代码",介绍的技术点是"希尔排序详解.实现代码.希尔排序.Java.实现.代码",希望对大 ...
- JAVA 多线程并发超详解
JAVA 多线程并发超详解(未完,下一篇文章还有) 1. JAVA 多线程并发 1.1.1. JAVA 并发知识库 1.1.2. JAVA 线程实现/创建方式 1.1.2.1. 继承 Thread 类 ...
- Java 泛型详解(超详细的java泛型方法解析)
Java 泛型详解(超详细的java泛型方法解析) 1. 什么是泛型 泛型:是一种把明确类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型.也就是说在泛型使用过程中,操作的数据类型被指定为 ...
- 【Java二维数组】(超详解)
[Java二维数组](超详解) 什么是二维数组 二维数组的定义格式 访问二维数组 什么是二维数组 元素为一维数组的数组就称为二维数组 二维数组的定义格式 格式一:元素的数据类型[][] 数组的名字 = ...
- Java虚拟机详解----JVM常见问题总结
[正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考本人之前的系列文章,尤其是那篇:Java虚拟机详解04----GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾 ...
- Mybatis案例超详解
Mybatis案例超详解 前言: 本来是想像之前一样继续跟新Mybatis,但由于种种原因,迟迟没有更新,快开学了,学了一个暑假,博客也更新了不少,我觉得我得缓缓,先整合一些案例练练,等我再成熟点理解 ...
- 接口与继承系列教材 (十)- Java 内部类详解
接口与继承系列教材 (十)- Java 内部类详解 内部类分为四种: 非静态内部类 静态内部类 匿名类 本地类 步骤1:非静态内部类 步骤2:静态内部类 步骤3:匿名类 步骤4:本地类 步骤5:在匿名 ...
最新文章
- 如何才能做好绩效管理?
- PacBio RS系列已被淘汰,PacBio Sequel成为三代测序最新起跑线。
- Python Flask学习知识点(七)
- Windows Server 2008英文正式版安装体验
- 2021-10-21 二叉堆 恋上数据结构笔记
- php实现商品购物车添加功能,PHP实现添加购物车功能
- Java使用Tomcat数据源的方式
- 作者:李文静,山东农业信息中心助理农经师。
- 给缺少Python项目实战经验的人,赶紧收藏!
- PyTorch 1.0 中文文档:多进程最佳实践
- 大文件打开工具 PilotEdit
- k8s技术预研11--kubernetes网络原理
- layabox 节点查找
- 傅里叶级数的通俗理解
- 透过CES看国产手机市场变动 “中华酷联”要调位
- 用python进行数据分析(一:数据理解)
- Premiere CS4无法导出视频
- colab使用入门(1)-安装库,保存/加载笔记本
- [总结]Android系统体系结构
- 你所不知的X86 CPU微码机制