Kruskal算法求最小生成树(java)
数据结构(Java版)图2(最小生成树)
最小生成树举例
A
50 60 52 65 50
C
45 42 30 50
A
C
45
B
40
D
G
B
40 50
D
42 30
G
E
70
F
E
F
(a) 无向带权连通图G
(b) 无向带权图G 的最小生成树T
从最小生成树的定义可知,构造n个顶点的无向带权连 通图的最小生成树,必须满足如下三个条件: ① 必须包含n个顶点。 ② 有且仅有n-1条边。 ③ 没有回路。
)
将ej边加入到tree中;
}
实践项目
设计一个程序实现Prim和Kruskal算法.
表5-1 lowcost[ ]数组数据变化情况 表5-2 closest[ ]数组数据变化情况
扫描次数
closest[0]
closest[1]
closest[2]
closest[3]
closest[4]
closest[5]
求最小生成树算法
普里姆算法(Prim) (从点着手)
适合于求边稠密的最小生成树 适合于求边稀疏的最小生成树
克鲁斯卡尔算法(Kruskal)(从边着手)
普里姆算法(Prim)思想
1.
2.
3.
4.
令集合U={u0}(即从顶点u0开始构造最小生 成树),集合T={}。 从所有顶点u∈U和顶点v∈V-U的边权中选择最 小权值的边(u,v),将顶点v加入到集合U中,边 (u,v)加入到集合T中。 如此重复下去,直到U=V时则最小生成树构造完 毕。 此时集合U就是最小生成树的顶点集合,集合T 就是最小生成树的边集。
Kruskal克鲁斯卡尔最小生成树算法(贪心算法)
Kruskal克鲁斯卡尔最⼩⽣成树算法(贪⼼算法)1. /*2. * Introduction to Algorithms3. * Chapter 23 --- MST.Kruskal4. * Tanky Woo @ 5. * 2012.1.76. */7.8. #include <</span>iostream>9. #include <</span>algorithm>10. using namespace std;11.12. const int maxint = 999999;13.14. typedef struct Road{15. int c1, c2;// a到b16. int value;//权值17. }Road;18.19. int no;20. int line;//记录实际关系数21. Road road[100];//设⼀个⽐较⼤的值,实际看输⼊最⼩⽣成树中:边数e=n-122. int node[101];//最⼩⽣成树:n顶点数23.24. bool myCmp(const Road &a,const Road &b)25. {26. if(a.value <</span> b.value)27. return 1;28. return 0;29. }30.31. //node[2]=1 node[8]=1 ,node[3]=1,共同的祖先,如果(3,8)加进去,则构成回路,不要32. //有点像并查集33. int Find_Set(int n)34. {35. if(node[n]==-1)36. return n;37. return node[n]= Find_Set(node[n]);38. }39.40. bool Merge(int s1,int s2)41. {42. int r1 = Find_Set(s1);43. int r2 = Find_Set(s2);44. if(r1 == r2)//如果相等证明构成回路,则直接返回⼀个0,不要把顶点加进来(下⼀步是加进去的)45. return 0;46. if(r1 <</span> r2)47. node[r2]= r1;48. else49. node[r1]= r2;50. return 1;51. }52.53. int main()54. {55. freopen("input.txt","r", stdin);56. //初始化全为-157. memset(node,-1, sizeof(node));58. scanf("%d",&no);59. scanf("%d",&line);60. int i;61. for(i=0; i<</span>line; ++i)62. {63. cin >> road[i].c1 >> road[i].c2 >> road[i].value;64. }65. sort(road, road+line, myCmp);66. int sum = 0, count = 0;// sum是MST的值,count是记录已使⽤的点数67. for(i=0; i<</span>line; ++i)68. {69. if(Merge(road[i].c1, road[i].c2))//如果返回的为0,则证明构成回路,不要加进70. {71. count ++;72. sum += road[i].value;73. }74. if(count == no-1)//e=n-1已经连通,可以退出75. break;76. }77. cout <</span><</span> sum <</span><</span> endl;78. return 0;79. }80.81.82. /*83. input.txt:84. 985. 1486. 1 2 487. 1 8 888. 2 3 889. 2 8 1190. 3 4 791. 3 6 492. 3 9 293. 4 5 994. 4 6 1495. 5 6 1096. 6 7 297. 7 8 198. 7 9 699. 8 9 7100. */。
最小生成树的Kruskal算法实现
#include<stdio.h>#include<stdlib.h>#define M 20#define MAX 20typedef struct{int begin;int end;int weight;}edge;typedef struct{int adj;int weight;}AdjMatrix[MAX][MAX];typedef struct{AdjMatrix arc;int vexnum, arcnum;}MGraph;void CreatGraph(MGraph *);//函数申明void sort(edge* ,MGraph *);void MiniSpanTree(MGraph *);int Find(int *, int );void Swapn(edge *, int, int);void CreatGraph(MGraph *G)//构件图{int i, j,n, m;printf("请输入边数和顶点数:\n");scanf("%d %d",&G->arcnum,&G->vexnum);for (i = 1; i <= G->vexnum; i++)//初始化图{for ( j = 1; j <= G->vexnum; j++){G->arc[i][j].adj = G->arc[j][i].adj = 0;}}for ( i = 1; i <= G->arcnum; i++)//输入边和权值{printf("请输入有边的2个顶点\n");scanf("%d %d",&n,&m);while(n < 0 || n > G->vexnum || m < 0 || n > G->vexnum) {printf("输入的数字不符合要求请重新输入:\n");scanf("%d%d",&n,&m);}G->arc[n][m].adj = G->arc[m][n].adj = 1;getchar();printf("请输入%d与%d之间的权值:\n", n, m);scanf("%d",&G->arc[n][m].weight);}printf("邻接矩阵为:\n");for ( i = 1; i <= G->vexnum; i++){for ( j = 1; j <= G->vexnum; j++){printf("%d ",G->arc[i][j].adj);}printf("\n");}}void sort(edge edges[],MGraph *G)//对权值进行排序{int i, j;for ( i = 1; i < G->arcnum; i++){for ( j = i + 1; j <= G->arcnum; j++){if (edges[i].weight > edges[j].weight){Swapn(edges, i, j);}}}printf("权排序之后的为:\n");for (i = 1; i < G->arcnum; i++){printf("<< %d, %d >> %d\n", edges[i].begin, edges[i].end, edges[i].weight); }}void Swapn(edge *edges,int i, int j)//交换权值以及头和尾{int temp;temp = edges[i].begin;edges[i].begin = edges[j].begin;edges[j].begin = temp;temp = edges[i].end;edges[i].end = edges[j].end;edges[j].end = temp;temp = edges[i].weight;edges[i].weight = edges[j].weight;edges[j].weight = temp;}void MiniSpanTree(MGraph *G)//生成最小生成树{int i, j, n, m;int k = 1;int parent[M];edge edges[M];for ( i = 1; i < G->vexnum; i++){for (j = i + 1; j <= G->vexnum; j++){if (G->arc[i][j].adj == 1){edges[k].begin = i;edges[k].end = j;edges[k].weight = G->arc[i][j].weight;k++;}}}sort(edges, G);for (i = 1; i <= G->arcnum; i++){parent[i] = 0;}printf("最小生成树为:\n");for (i = 1; i <= G->arcnum; i++)//核心部分{n = Find(parent, edges[i].begin);m = Find(parent, edges[i].end);if (n != m)//判断是否有回路,如果有,舍弃{parent[m] = n;printf("<< %d, %d >> %d\n", edges[i].begin, edges[i].end, edges[i].weight); }}}int Find(int *parent, int f)//找尾{while ( parent[f] > 0){f = parent[f];}return f;}int main(void)//主函数{MGraph *G;G = (MGraph*)malloc(sizeof(MGraph));if (G == NULL){printf("memory allcation failed,goodbye");exit(1);}CreatGraph(G);MiniSpanTree(G);system("pause");return 0;}/%BD%F5%B1%F3ljb/blog/item/7bce9a339f74f049ac4b5f30.html#include "heap.h"#include "UFSets.h"template <class T, class E>void Kruskal (Graph<T, E>& G,MinSpanTree<T, E>& MST) {MSTEdgeNode<T, E> ed; //边结点辅助单元int u, v, count;int n = G.NumberOfVertices(); //顶点数int m = G.NumberOfEdges(); //边数MinHeap <MSTEdgeNode<T, E>> H(m); //最小堆UFSets F(n); //并查集for (u = 0; u < n; u++)for (v = u+1; v < n; v++)if (G.getWeight(u,v) != maxValue) {ed.tail = u; ed.head = v; //插入堆ed.cost = G.getWeight (u, v);H.Insert(ed);count = 1; //最小生成树边数计数while (count < n) { //反复执行, 取n-1条边H.Remove(ed); //退出具最小权值的边u = F.Find(ed.tail); v = F.Find(ed.head);//取两顶点所在集合的根u与vif (u != v) { //不是同一集合,不连通F.Union(u, v); //合并,连通它们MST.Insert(ed); //该边存入MSTcount++;}}};。
数据结构-kruskal算法求最小生成树_实验报告
一、问题简述题目:图的操作。
要求:用kruskal算法求最小生成树。
最短路径:①输入任意源点,求到其余顶点的最短路径。
②输入任意对顶点,求这两点之间的最短路径和所有路径。
二、程序设计思想首先要确定图的存储形式。
经过的题目要求的初步分析,发现该题的主要操作是路径的输出,因此采用边集数组(每个元素是一个结构体,包括起点、终点和权值)和邻接矩阵比较方便以后的编程。
其次是kruskal算法。
该算法的主要步骤是:GENERNIC-MIT(G,W)1. A←2. while A没有形成一棵生成树3 do 找出A的一条安全边(u,v);4.A←A∪{(u,v)};5.return A算法设置了集合A,该集合一直是某最小生成树的子集。
在每步决定是否把边(u,v)添加到集合A中,其添加条件是A∪{(u,v)}仍然是最小生成树的子集。
我们称这样的边为A 的安全边,因为可以安全地把它添加到A中而不会破坏上述条件。
然后就是Dijkstra算法。
Dijkstra算法基本思路是:假设每个点都有一对标号 (d j, p j),其中d j是从起源点s到点j的最短路径的长度 (从顶点到其本身的最短路径是零路(没有弧的路),其长度等于零);p j则是从s到j的最短路径中j点的前一点。
求解从起源点s到点j的最短路径算法的基本过程如下:1) 初始化。
起源点设置为:① d s=0, p s为空;②所有其他点: d i=∞, p i=?;③标记起源点s,记k=s,其他所有点设为未标记的。
2) 检验从所有已标记的点k到其直接连接的未标记的点j的距离,并设置:d j=min[d j, d k+l kj]式中,l kj是从点k到j的直接连接距离。
3) 选取下一个点。
从所有未标记的结点中,选取d j中最小的一个i:d i=min[d j, 所有未标记的点j]点i就被选为最短路径中的一点,并设为已标记的。
4) 找到点i的前一点。
从已标记的点中找到直接连接到点i的点j*,作为前一点,设置:i=j*5) 标记点i。
Kruskal算法计算最小生成树(java)
J avaMan_chen的专栏K ruskal算法计算最小生成树(java)分类: 算法 2012-12-04 17:15 243人阅读 评论(2) 收藏举报kruskalKruskal克鲁斯卡尔最小生成树最小生成树定义:每一个无向图可拆分成多个子图,在这些子图中,如果图的各个顶点没有形成回路,则是图的一颗生成树。
最小生成树的意识是树的相邻节点距离之和最小。
应用场景:张三被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。
张三已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。
为了用最小的消费,他想铺设最短的光纤去连接所有的农场,问要如何实现。
算法实现:有关最小生成树的问题常见的算法有两种,分别是Kruskal(克鲁斯卡尔)算法和Prim(普里姆)算法,本文讲解Kruskal算法的实现Kruskal算法的计算流程大致如下:1.将无向图的边按距离长短递增式排序,放到集合中2.遍历该集合,找出最短的边,加入到结果生成树的集合中3.如果结果生成树出现回路,则放弃这条边4.重新执行步骤2,直至所有顶点被遍历可以看出在每次遍历过程中采用了贪心算法算法实例图:代码实现:Edge类用与封装无向图中每条边的信息public class Edge implements Comparable<Edge>{private String start;private String end;private int distance;public Edge(String start,String end,int distance){this.start=start;this.end=end;this.distance=distance;}public String getStart() {return start;}public void setStart(String start) {this.start = start;}public String getEnd() {return end;}public void setEnd(String end) {this.end = end;}public int getDistance() {return distance;}public void setDistance(int distance) {this.distance = distance;}@Overridepublic String toString() {return start + "->" + end;}@Overridepublic int compareTo(Edge obj) {int targetDis=obj.getDistance();return distance>targetDis?1:(distance==targetDis?0:-1);}}MapBuilder类用于构建数据源(数据源结构如上图所示):public class MapBuilder {public TreeSet<Edge> build(){TreeSet<Edge> edges=new TreeSet<Edge>();edges.add(new Edge("A","B",1));edges.add(new Edge("A","C",4));edges.add(new Edge("A","F",6));edges.add(new Edge("B","D",8));edges.add(new Edge("B","E",3));edges.add(new Edge("C","F",5));edges.add(new Edge("C","E",9));edges.add(new Edge("D","E",7));edges.add(new Edge("D","F",10));edges.add(new Edge("E","F",2));return edges;}public int getPointNum(){return 6;}}Kruskal类用于计算最小生成树public class Kruskal {private Set<String> points=new HashSet<String>();private List<Edge> treeEdges=new ArrayList<Edge>();public void buildTree(){MapBuilder builder=new MapBuilder();TreeSet<Edge> edges=builder.build();int pointNum=builder.getPointNum();for(Edge edge:edges){if(isCircle(edge)){continue;}else{//没有出现回路,将这条边加入treeEdges集合treeEdges.add(edge);//如果边数等于定点数-1,则遍历结束if(treeEdges.size()==pointNum-1){return;}}}}public void printTreeInfo(){int totalDistance=0;for(Edge edge:treeEdges){totalDistance+=edge.getDistance();System.out.println(edge.toString());}System.out.println("总路径长度:"+totalDistance);}private boolean isCircle(Edge edge){int size=points.size();if(!points.contains(edge.getStart())){size++;}if(!points.contains(edge.getEnd())){size++;}if(size==treeEdges.size()+1){return true;}else{points.add(edge.getStart());points.add(edge.getEnd());return false;}}}Main类用于测试Kruskal算法public class Main {public static void main(String[] args) {Kruskal test=new Kruskal();test.buildTree();test.printTreeInfo();}}打印输出:A->BE->FB->EA->CD->E总路径长度:17。
Kruskal算法求最小生成树(java)
Kruskal算法求最小生成树(JA V A)代码:package homework;import java.util.Scanner;import java.util.Arrays;import java.util.ArrayList;class Edge {public int start;//始边public int end;//终边public double cost;//权重}public class MinSpanningTree_Kruskal{private static int MAX = 100;private ArrayList<Edge> edge = new ArrayList<Edge>();//整个图的边private ArrayList<Edge> target = new ArrayList<Edge>();//目标边,最小生成树private int[] parent = new int[MAX];//标志所在的集合private static double INFINITY = 99999999.99;//定义无穷大private double mincost = 0.0;//最小成本private int n;//结点个数public MinSpanningTree_Kruskal(){}public static void main(String args[]){MinSpanningTree_Kruskal sp = new MinSpanningTree_Kruskal();sp.init();sp.kruskal();sp.print();}//初始化public void init(){Scanner scan = new Scanner(System.in);int p,q;double w;System.out.println("请输入结点个数:");n = scan.nextInt();System.out.println("请输入各条边及权值(每次输入一组数据按回车确认," +"最后输入-1 -1 -1 结束输入过程)");while(true){p = scan.nextInt();q = scan.nextInt();w = scan.nextDouble();if(p < 0 || q < 0 || w < 0){break;}Edge e = new Edge();e.start = p; e.end = q; e.cost = w;edge.add(e);}mincost = 0.0;for(int i = 1; i <= n; ++i){parent[i] = i;}}//集合合并public void union(int j, int k){for(int i = 1; i <= n; ++i){if(parent[i] == j){parent[i] = k;}}}//prim算法主体public void kruskal(){//找剩下的n-2条边int i = 0;while(i < n-1 && edge.size() > 0){//每次取一最小边,并删除double min = INFINITY;int tag = 0;Edge tmp = null;for(int j = 0; j < edge.size(); ++j){Edge tt = edge.get(j);if(tt.cost < min){min = tt.cost;tmp = tt;}}int jj = parent[tmp.start];int kk = parent[tmp.end];//去掉环if(jj != kk){++i;target.add(tmp);mincost += tmp.cost;union(jj,kk);}edge.remove(tmp);}if(i != n-1){System.out.println("没有最小生成树");System.exit(0);}}//打印结果public void print(){double sum=0;System.out.println("最小生成树:");for(int i = 0; i < target.size(); ++i){Edge e = target.get(i);System.out.println("第" + (i+1) + "条边: " + e.start + "---" + e.end+ " 权值:" + e.cost);sum=sum+e.cost;}System.out.println("最小生成树的权值:" + sum);}}调试结果:。
Kruskal算法求最小生成树
荆楚理工学院课程设计成果学院:_______计算机工程学院__________ 班级: 14计算机科学与技术一班学生姓名: 陈志杰学号: 2014407020137设计地点(单位)_____B5101_________ ____________设计题目:克鲁斯卡尔算法求最小生成树__________________________________完成日期:2015年1月6日指导教师评语: ______________ ____________________________________________________________________________________________________________ ___________________________________________________________________________________________ ___________________________ __________ _成绩(五级记分制):_____ _ __________教师签名:__________ _______________注:介于A和C之间为B级,低于C为D级和E级。
按各项指标打分后,总分在90~100为优,80~89为良,70~79为中,60~69为及格,60分以下为不及格。
目录1 需求分析 (1)1.1系统目标 (1)1.2主体功能 (1)1.3开发环境 (1)2 概要设计 (1)2.1功能模块划分 (1)2.2 系统流程图 (2)3 详细设计 (3)3.1 数据结构 (3)3.2 模块设计 (3)4测试 (3)4.1 测试数据 (3)4.2测试分析 (4)5总结与体会 (6)5.1总结: (6)5.2体会: (6)参考文献 (7)附录全部代码 (8)1 需求分析1.1系统目标Kruskal算法是一种按照网中边的权值递增的顺序构造最小生成树的方法。
贪心策略-最小生成树prim和克利斯卡尔java算法源程序
实验报告9课程数据构造与算法实验名称贪心策略第页班级11计本学号姓名风律澈实验日期:2021年4月27日报告退发(订正、重做)一、实验目的掌握贪心策略的原理和应用。
二、实验环境1、微型计算机一台2、WINDOWS操作系统,Java SDK,Eclipse开发环境三、实验内容必做题:1、编写程序,实现最小生成树prim算法。
2、编写程序,实现最小生成树Kruskal算法。
四、实验步骤和结果(附上代码和程序运行结果截图)1,primpublic class main {/***@param args*/public static final int maxvalue=Integer.MAX_VALUE;public static void// TODO Auto-generated method stubint weight[][]={{0,6,1,5,maxvalue,maxvalue},{6,0,5,maxvalue,3,maxvalue},{1,5,0,5,6,4},{5,maxvalue,5,0,maxvalue,2},{maxvalue,3,6,maxvalue,0,6},{maxvalue,maxvalue,4,2,6,0},};graph a=new graph(weight);a.showprimtree();}}importimportpublic class graph {private ArrayList<vex> vexs;//定义顶点,进入顶点定义初始化public graph(int weight[][]){super();this.vexs=new ArrayList<vex>();//生成顶点集对象实例//start和end是在下面程序中使用以构造边的//vex start;vex end;for(int i=0;i<weight.length;i++)//对顶点集的每个元素生成点对象实例this.vexs.add(new vex());for(int i=0;i<weight.length;i++){//对每个元素进展构造初始化start=this.vexs.get(i);for(int j=0;j<weight.length;j++){if(weight[i][j]!=Integer.MAX_VALUE){end=this.vexs.get(j);new side(start,end,weight[i][j]);}}}}//至此图的所有成分的信息已经完成,返回mainpublic ArrayList<side> prim(){ArrayList<side> tree=new ArrayList<side>();PriorityQueue<side> pq=new PriorityQueue<side>();vex v = this.vexs.get(0);v.setcheck(1);side s;pq.addAll(v.getsides());while (true) {if(pq.isEmpty())break;s=pq.poll();if(s.check_intree()==1){s.un_in();continue;}v=s.add_tree();tree.add(s);pq.addAll(v.getsides());}return tree;}public void showprimtree() {System.out.println(prim());}}importpublic class vex {private static int ids=0;private int id;private int check;ArrayList<side> sides;public vex(){super();id=ids++;check=0;sides=new ArrayList<side>();}public int getid(){return id;}public int getcheck(){return check;}public void setcheck(int i){this.check=i;}public ArrayList<side> getsides(){return sides;}public void addside(side s){this.sides.add(s);}}public class side implements Comparable<side>{private vex start;private vex end;private int weight;private int state;//0表示没有动过,1表示处理过,2表示参加树public side(vex s, vex e, int w) {// TODO Auto-generated constructor stubsuper();this.start=s;this.end=e;this.weight=w;this.state=0;s.addside(this);e.addside(this);}public vex add_tree(){if(this.start.getcheck()==0){start.setcheck(1);this.state=2;return start;}end.setcheck(1);return end;}public int check_intree(){if(start.getcheck()+end.getcheck()==2) return 1;return 0;}public int check_idea(){if (this.state>0) return 1;elsereturn 0;}public void un_in(){this.state=1;}@Overridepublic int compareTo(side o) {// TODO Auto-generated method stubif(this.weight>o.weight) return 1;if(this.weight<o.weight) return -1;return 0;}public String toString(){return"边("+this.start.getid()+","+this.end.getid()+")"; }}2.kruscal算法package最小生成树;public class main {/*** @param args*/public static final int maxvalue=Integer.MAX_VALUE;public static void main(String[] args) {// TODO Auto-generated method stubint weight[][]={{0,6,1,5,maxvalue,maxvalue},{6,0,5,maxvalue,3,maxvalue},{1,5,0,5,6,4},{5,maxvalue,5,0,maxvalue,2},{maxvalue,3,6,maxvalue,0,6},{maxvalue,maxvalue,4,2,6,0},};graph a=new graph(weight);a.showkurscaltree();}}package最小生成树;importimportpublic class graph {private ArrayList<vex> vexs;//定义顶点,进入顶点定义初始化private ArrayList<side> sides;public graph(int weight[][]){super();this.vexs=new ArrayList<vex>();//生成顶点集对象实例this.sides=new ArrayList<side>();//start和end是在下面程序中使用以构造边的//vex start;vex end;for(int i=0;i<weight.length;i++)//对顶点集的每个元素生成点对象实例this.vexs.add(new vex());for(int i=0;i<weight.length;i++){//对每个元素进展构造初始化start=this.vexs.get(i);for(int j=0;j<weight.length;j++){if(weight[i][j]!=Integer.MAX_VALUE){end=this.vexs.get(j);this.sides.add(newside(start,end,weight[i][j]));}}}}//至此图的所有成分的信息已经完成,返回mainpublic ArrayList<side> kurscal(){ArrayList<side> tree=new ArrayList<side>();PriorityQueue<side> pq=new PriorityQueue<side>();pq.addAll(this.sides);side s;while (true) {if(pq.isEmpty())break;s=pq.poll();if(s.together()==1){tree.add(s);}}return tree;}public void showkurscaltree() {System.out.println(kurscal());}}package最小生成树;importpublic class vex {private static int ids=1;private int id;ArrayList<vex> vexs;public vex(){super();id=ids++;this.vexs=new ArrayList<vex>();this.vexs.add(this);}public int getid(){return id;}public ArrayList<vex> getvexs(){return vexs;}public void setvexs(ArrayList<vex> vs){this.vexs.remove(this);vs.add(this);this.vexs=vs;}}package最小生成树;importpublic class side implements Comparable<side>{private vex start;private vex end;private int weight;public side(vex s, vex e, int w) {// TODO Auto-generated constructor stubsuper();this.start=s;this.end=e;this.weight=w;}@Overridepublic int compareTo(side o) {// TODO Auto-generated method stubif(this.weight>o.weight) return 1;if(this.weight<o.weight) return -1;return 0;}public String toString(){return"边("+this.start.getid()+","+this.end.getid()+")";}public int together() {// TODO Auto-generated method stubArrayList<vex> vexsstart=start.getvexs();ArrayList<vex> vexsend=end.getvexs();ArrayList<vex> vexst;vex v;if(vexsstart==vexsend)return 0;if(vexsstart.size()<vexsend.size()){vexst=vexsstart;vexsstart=vexsend;vexsend=vexst;}while(true){if(vexsend.isEmpty())break;v=vexsend.get(0);v.setvexs(vexsstart);}return 1;}}五、实验总结(本次实验完成的情况,心得体会)。
克鲁斯卡尔算法求最小生成树完整代码
克鲁斯卡尔算法是一种用来求解最小生成树(Minimum Spanning Tree)的经典算法,它采用了贪心策略,能够高效地找到图中的最小生成树。
下面将为大家介绍克鲁斯卡尔算法的完整代码,希望对大家有所帮助。
1. 算法思路克鲁斯卡尔算法的基本思路是:首先将图中的所有边按照权值进行排序,然后从小到大依次考虑每条边,如果加入该边不会构成环,则将其加入最小生成树中。
在算法执行过程中,我们需要使用并查集来判断是否会构成环。
2. 代码实现接下来,我们将给出克鲁斯卡尔算法的完整代码,代码使用C++语言编写,具体如下:```cpp#include <iostream>#include <vector>#include <algorithm>using namespace std;// 定义图的边struct Edge {int u, v, weight;Edge(int u, int v, int weight) : u(u), v(v), weight(weight) {} };// 定义并查集class UnionFind {private:vector<int> parent;public:UnionFind(int n) {parent.resize(n);for (int i = 0; i < n; i++) {parent[i] = i;}}int find(int x) {if (parent[x] != x) {parent[x] = find(parent[x]);}return parent[x];}void Union(int x, int y) {int root_x = find(x);int root_y = find(y);if (root_x != root_y) {parent[root_x] = root_y;}}};// 定义比较函数用于排序bool cmp(const Edge a, const Edge b) {return a.weight < b.weight;}// 克鲁斯卡尔算法vector<Edge> kruskal(vector<Edge> edges, int n) { // 先对边进行排序sort(edges.begin(), edges.end(), cmp);// 初始化最小生成树的边集vector<Edge> res;UnionFind uf(n);for (int i = 0; i < edges.size(); i++) {int u = edges[i].u, v = edges[i].v, weight = edges[i].weight; // 判断是否构成环if (uf.find(u) != uf.find(v)) {uf.Union(u, v);res.push_back(edges[i]);}}return res;}// 测试函数int m本人n() {vector<Edge> edges;edges.push_back(Edge(0, 1, 4));edges.push_back(Edge(0, 7, 8));edges.push_back(Edge(1, 2, 8));edges.push_back(Edge(1, 7, 11));edges.push_back(Edge(2, 3, 7));edges.push_back(Edge(2, 5, 4));edges.push_back(Edge(2, 8, 2));edges.push_back(Edge(3, 4, 9));edges.push_back(Edge(3, 5, 14));edges.push_back(Edge(4, 5, 10));edges.push_back(Edge(5, 6, 2));edges.push_back(Edge(6, 7, 1));edges.push_back(Edge(6, 8, 6));edges.push_back(Edge(7, 8, 7));vector<Edge> res = kruskal(edges, 9);for (int i = 0; i < res.size(); i++) {cout << res[i].u << " " << res[i].v << " " << res[i].weight << endl;}return 0;}```3. 算法实例上述代码实现了克鲁斯卡尔算法,并对给定的图进行了最小生成树的求解。
数学建模-最小生成树-kruskal算法及各种代码
kruskal算法及代码之阳早格格创做---含真代码、c代码、matlab、pascal等代码K r u s k a l算法屡屡采用n- 1条边,所使用的贪婪规则是:从剩下的边中采用一条不会爆收环路的具备最小泯灭的边加进已采用的边的集中中.注意到所采用的边若爆收环路则不可能产死一棵死成树.K r u s k a l算法分e 步,其中e 是搜集中边的数目.按泯灭递加的程序去思量那e 条边,屡屡思量一条边.当思量某条边时,若将其加进到已选边的集中中会出现环路,则将其扬弃,可则,将它选进.目录Kruskal算法1.算法定义举例形貌Kruskal算法的代码真止1.真代码C代码真止matlab代码真止pascal代码真止Kruskal算法1.算法定义举例形貌Kruskal算法的代码真止1.真代码C代码真止matlab代码真止pascal代码真止算法定义克鲁斯卡我算法假设WN=(V,{E}) 是一个含有n 个顶面的连通网,则依照克鲁斯卡我算法构制最小死成树的历程为:先构制一个只含n 个顶面,而边集为空的子图,若将该子图中各个顶面瞅成是各棵树上的根结面,则它是一个含有n 棵树的一个森林.之后,从网的边集E 中采用一条权值最小的边,若该条边的二个顶面分属分歧的树,则将其加进子图,也便是道,将那二个顶面分别地方的二棵树合成一棵树;反之,若该条边的二个顶面已降正在共一棵树上,则不可与,而该当与下一条权值最小的边再试之.依次类推,曲至森林中惟有一棵树,也即子图中含有n-1条边为止.举例形貌克鲁斯卡我算法(Kruskal's algorithm)是二个典范的最小死成树算法的较为简朴明白的一个.那内里充分体现了贪心算法的粗髓.大概的过程不妨用一个图去表示.那里的图的采用借用了Wikipedia上的那个.非常浑晰且曲瞅.最先第一步,咱们有一弛图,有若搞面战边如下图所示:第一步咱们要搞的事务便是将所有的边的少度排序,用排序的截止动做咱们采用边的依据.那里再次体现了贪心算法的思维.资材排序,对付局部最劣的资材举止采用.排序完毕后,咱们率先采用了边AD.那样咱们的图便形成了第二步,正在剩下的变中觅找.咱们找到了CE.那里边的权沉也是5依次类推咱们找到了6,7,7.完毕之后,图形成了那个格式..下一步便是闭键了.底下采用那条边呢?BC大概者EF 吗?皆不是,纵然目前少度为8的边是最小的已采用的边.然而是目前他们已经连通了(对付于BC不妨通过CE,EB去对接,类似的EF不妨通过EB,BA,AD,DF去接连).所以咱们不需要采用他们.类似的BD也已经连通了(那里上图的连通线用白色表示了).末尾便剩下EG战FG了.天然咱们采用了EG.末尾乐成的图便是下图:.到那里所有的边面皆已经连通了,一个最小死成树构修完毕.编写本段Kruskal算法的代码真止真代码MST-KRUSKAL(G,w)C代码真止Copyright (c) 2002,2006 by ctu_85All Rights Reserved.*//* I am sorry to say that the situation of unconnected graph is not concerned */#include "stdio.h"#define maxver 10#define maxright 100int G[maxver][maxver],record=0,touched[maxver][maxver]; int circle=0;intFindCircle(int,int,int,int);int main(){int path[maxver][2],used[maxver][maxver];inti,j,k,t,min=maxright,exsit=0;int v1,v2,num,temp,status=0;restart:printf("Please enter the number of vertex(s) in the graph:\n"); scanf("%d",&num);if(num>maxver||num<0){printf("Error!Pleasereinput!\n");goto restart;}for(j=0;j<num;j++)for(k=0;k<num;k++){if(j==k)G[j][k]=maxright;used[j][k]=1;touched[j][k]=0;}elseif(j<k){re:printf("Please input the right between vertex %d and vertex %d,if no edge exists please input -1:\n",j+1,k+1);scanf("%d",&temp);if(temp>=maxright||temp<-1){printf("Invalid input!\n");goto re;}if(temp==-1)temp=maxright;G[j][k]=G[k][j]=temp;used[j][k]=used[k][j]=0;touched[j][k]=touched[k][j]=0;}for(j=0;j<num;j++){path[j][0]=0;path[j][1]=0;}for(j=0;j<num;j++){status=0;for(k=0;k<num;k++)if(G[j][k]<maxright){status=1;break;}if(status==0)break;}for(i=0;i<num-1&&status;i++) {for(j=0;j<num;j++)for(k=0;k<num;k++)if(G[j][k]<min&&!used[j][k]){v1=j;v2=k;min=G[j][k];}if(!used[v1][v2]){used[v1][v2]=1;used[v2][v1]=1;touched[v1][v2]=1;touched[v2][v1]=1;path[0]=v1;path[1]=v2;for(t=0;t<record;t++)FindCircle(path[t][0],path[t][0],num,path[t][0]); if(circle){/*if a circle exsits,roll back*/circle=0;i--;exsit=0;touched[v1][v2]=0;touched[v2][v1]=0;min=maxright;}else{record++;min=maxright;}}}if(!status)printf("We cannot deal with it because the graph is not connected!\n");else{for(i=0;i<num-1;i++)printf("Path %d:vertex %d tovertex %d\n",i+1,path[0]+1,path[1]+1);}return 1;}intFindCircle(intstart,intbegin,inttimes,int pre) { /* to judge whether a circle is produced*/ inti;for(i=0;i<times;i++)if(touched[begin]==1){if(i==start&&pre!=start){circle=1;return 1;break;}elseif(pre!=i)FindCircle(start,i,times,begin);elsecontinue;}return 1;}matlab代码真止functionKruskal(w,MAX)%此步调为最小收撑树的Kruskal算法真止%w为无背图的距离矩阵,故为对付称矩阵%MAX为距离矩阵中∞的本质输进值%时间:2011年6月22日0:07:53len=length(w); %图的面数edge=zeros(len*(len-1),3); %用于死存图中的边count=1; %图中的边数for i=1:len-1 %循环距离矩阵,记录死存边for j=i+1:lenif w(i,j)~=MAXedge(count,1)=w(i,j);edge(count,2)=i;edge(count,3)=j;count=count+1;endendendedge=edge(1:count-1,:); %去掉无用边[tmp,index]=sort(edge(:,1)); %所有边按降序排序i=3; %本去尝试边数为3条(3条以下无法形成圈,即无需检测)while 1x=findcycle(edge(index(1:i),:),len); %检测那些边是可形成圈if xindex(i)=0; %若形成圈,则将该边对付应的index项标记表记标帜为0,以便与消elsei=i+1; %若不形成圈,则i加1,加进下一边检测endindex=index(index>0); %将形成圈的边从index中与消ifi==lenbreak; %找到切合条件的面数减一条的边,即找到一个最小收撑树endendindex=index(1:len-1); %截短index矩阵,死存前len-1项%%%%%%%%%%%% 截止隐现%%%%%%%%%%%%%s=sprintf('\n\t%s\t%s\t %s\t','边端面','距离','是可正在最小收撑树');fori=1:count-1edge_tmp=edge(i,:);if ~isempty(find(index==i,1))s_tmp=sprintf('\n \t (%d,%d)\t %d\t %s\t',edge_tmp(2),edge_tmp(3),edge_tmp(1),'√');elses_tmp=sprintf('\n \t (%d,%d)\t %d\t %s\t',edge_tmp(2),edge_tmp(3),edge_tmp(1),'×');ends=strcat(s,s_tmp);enddisp(s);endfunctionisfind=findcycle(w,N)%本步调用于推断所给的边是可形成圈:有圈,返回1;可则返回0%w:输进的边的矩阵%N:本图的面数%本理:不竭与消出现次数小于2的端面地方的边,末尾瞅察是可有边留住len=length(w(:,1));index=1:len;while 1num=length(index); %边数p=zeros(1,N); %用于死存各面的出现的次数(一条边对付应二个端面)for i=1:num %统计各面的出现次数p(w(index(i),2))=p(w(index(i),2))+1;p(w(index(i),3))=p(w(index(i),3))+1;endindex_tmp=zeros(1,num); %记录与消出现次数小于2的端面地方的边的边的下标集中discard=find(p<2); %找到出现次数小于2的端面count=0; %记录结余的边数fori=1:num%推断各边是可有仅出现一次端面——不,则记录其序号于index_tmpif ~(~isempty(find(discard==w(index(i),2),1)) ||~isempty(find(discard==w(index(i),3),1)))count=count+1;index_tmp(count)=index(i);endendif num==count %当不边被被与消时,循环停止index=index_tmp(1:count); %革新indexbreak;elseindex=index_tmp(1:count); %革新indexendendif isempty(index) %若末尾剩下的边数为0,则无圈isfind=0;elseisfind=1;endend%% a =[% 0 3 2 3 100 100100% 3 0 2 100 100100 6% 2 2 0 3 100 1 100% 3 100 3 0 5 100 100% 100 100100 5 0 4 6% 100 100 1 100 4 0 5% 100 6 100 6 100 5 0];%% Kruskal(a,100)pascal代码真止{最小死成树的Kruskal算法.Kruskal算法基础思维:屡屡选不属于共一连通分量(包管不死成圈)且边权值最小的顶面,将边加进MST,并将地方的2个连通分量合并,曲到只剩一个连通分量排序使用Quicksort(O(eloge))查看是可正在共一连通分量用Union-Find,屡屡Find战union运算近似常数Union-Find使用rank开收式合并战路径压缩总搀纯度O(eloge)=O(elogv) (果为e<n(n-1)/2)}constmaxn=100;maxe=maxn*maxn;typeedge=recorda,b :integer; //边的2个顶面len :integer; //边的少度end;varedges :array[0..maxe]of edge; //死存所有边的疑息p,r :array[0..maxn]of integer; //p死存i的女亲节面,r用去真止Union-Find的rank开收式n,e :integer; //n为顶面数,e为边数procedure swap(a,b:integer); //接换beginedges[0]:=edges[a];edges[a]:=edges[b];edges[b]:=edges[0];end;procedure quicksort(l,r:integer); //赶快排序varx,i,j :integer;beginx:=edges[random(r-l+1)+l].len;i:=l;j:=r;repeatwhile edges[i].len<x do inc(i);while edges[j].len>x do dec(j);ifi<=j thenbeginswap(i,j);inc(i);dec(j);enduntili>j;if l<j then quicksort(l,j);ifi<r then quicksort(i,r);end;procedureinit;vari :integer;beginassign(input,'g.in');reset(input);readln(n,e);for i:=1 to e do readln(edges[i].a,edges[i].b,edges[i].len); //从文献读进图的疑息for i:=1 to n do p[i]:=i; //初初化并查集randomize;quicksort(1,e); //使用赶快排序将边按权值从小到大排列end;function find(x:integer):integer; //并查集的Find,用去推断2个顶面是可属于一个连通分量beginif x<>p[x] then p[x]:=find(p[x]);find:=p[x]end;procedure union(a,b:integer); //如果不属于且权值最小则将2个顶面合并到一个连通分量vart :integer;begina:=find(a);b:=find(b);if r[a]>r[b] then begin t:=a;a:=b;b:=t end;if r[a]=r[b]then inc(r[a]);p[a]:=b;end;procedure kruskal; //主历程varen :integer; //en为目前边的编号count :integer; //统计举止了频频合并.n-1次合并后便得到最小死成树tot :integer; //统计最小死成树的边权总战begincount:=0;en:=0; tot:=0;while count<n-1 dobegininc(en);with edges[en] dobeginif find(a)<>find(b) thenbeginunion(a,b);writeln(a,'--',b,':',len);inc(tot,len);inc(count);end;end;end;writeln('Total Length=',tot)end;{===========main==========} begininit;kruskal;end.例题详睹vijos p1045 Kerry 的电缆搜集typerec=recordx,y:longint;cost:real;end;varf:array[1..1000000] of rec;s,ans:real;i,n,m,k,dad:longint;father:array[1..1000000] of longint; procedurekp(l,r:longint);vari,j:longint;xx:real;y:rec;begini:=l;j:=r;xx:=f[(i+j) div 2].cost;repeatwhile xx>f[i].cost do inc(i);while xx<f[j].cost do dec(j);ifi<=j thenbeginy:=f[i];f[i]:=f[j];f[j]:=y;inc(i);dec(j);end;untili>j;ifi<r then kp(i,r);if l<j then kp(l,j);end;function find(x:longint):longint; beginif father[x]=x then exit(x);father[x]:=find(father[x]);exit(father[x]);end;procedure union(x,y:longint;j:real); beginx:=find(x);y:=find(y);if x<>y thenbeginfather[y]:=x;ans:=ans+j;inc(k);end;end;beginreadln(s);readln(n);m:=0;while not eof do begininc(m);with f[m] doreadln(x,y,cost); end;if m<n-1 then beginwriteln('Impossible'); exit;end;fori:=1 to n do father[i]:=i;kp(1,m);k:=0;fori:=1 to m dobeginif k=n-1 then break;union(f[i].x,f[i].y,f[i].cost);end;if k<n-1 thenbeginwriteln('Impossible');exit;end;ifans>s then writeln('Impossible') elsewriteln('Need ',ans:0:2,' miles of cable');end.Kruskal算法适用于边稀稀的情形,而Prim算法适用于边稀稀的情形其余最小死成树算法c++代码真止#include <stdio.h>#include <stdlib.h>#include <vector>using namespace std;#define MAXNUM_VERTEX 20 //最多有20个顶面#define MAXNUM_EDGE 21typedefstruct{intv,w;int weight;}Edge;typedefstruct{int vertex[MAXNUM_VERTEX];Edge edge[MAXNUM_EDGE];intnum_vertex,num_edge;}Graph;Graph graph; //声明为齐部变量boolsearch_vertex(intver){for(inti=0; i<graph.num_vertex; i++)if(ver == graph.vertex[i] )return 1;printf("the vertex %d you input is not existed! \n",ver); return 0;}voidcreate_graph(){//输进顶面疑息printf("input the number of vertex in the graph\n");scanf(" %d",&graph.num_vertex);printf("input the vertex of graph,like 1,2\n");for(inti=0; i<graph.num_vertex; i++)scanf(" %d",&graph.vertex[i]);//输进边疑息printf("input the number of edge in the graph\n");scanf(" %d",&graph.num_edge);printf("intput the edge of graph and the weight of line,like 1-2 5\n");for(int j=0; j<graph.num_edge; j++){p1:inta,c,d;char b;scanf(" %d %c %d %d",&a,&b,&c,&d);if(search_vertex(a) && search_vertex(c) ){graph.edge[j].v=a;graph.edge[j].w=c;graph.edge[j].weight=d;}elsegoto p1;}}voidsort_by_weight(){for(inti=1; i<graph.num_edge; i++){Edge temp=graph.edge[i];for(int j=i-1; j>=0 && graph.edge[j].weight>temp.weight; j--) graph.edge[j+1]=graph.edge[j];graph.edge[j+1]=temp;}}/*不相接集处理函数*/inline void makeset(vector<int> & array){for(inti=0; i<array.size(); i++)array[i]=i;}intfindset(vector<int> & parent,inti){if(i != parent[i])i=parent[i];returni;}inline void merge(vector<int> & parent,inti,int j) {parent[i]=j;}/*不相接集处理函数*/voidkruskal(){intnum_ver=graph.num_vertex;int count=0;vector<int> parent_ver;parent_ver.resize(num_ver);/*核心部分是用不相接集中成树*/ makeset(parent_ver);printf("the edge of min tree as follow: \n");for( inti=0; i<num_ver && count<num_ver-1; i++ ) //count 表示合并(merge)的次数num_ver-1次{int m=graph.edge[i].v;int n=graph.edge[i].w;int w=graph.edge[i].weight;if(findset(parent_ver,m) != findset(parent_ver,n)) //当属于分歧的集中时,则将该边增加进树中{printf("(%d %d) %d\n",m,n,w);merge(parent_ver,m,n);count++;}}}voidprint_edge(){printf("the graph you input as follow: \n");for(inti=0; i<graph.num_edge; i++)printf("%d-%d the weightis: %d\n",graph.edge[i].v,graph.edge[i].w,graph.edge[i].weight);}void main(){create_graph();sort_by_weight();print_edge();kruskal();}java代码真止importjava.util.ArrayList;importjava.util.Collections;class Bian implements Comparable // 二面之间的加权边{private intfirst,second;// 表示一条边的二个节面private int value;// 权值publicBian(intfirst,intsecond,int value) {this.first = first;this.second = second;this.value = value;}publicintgetFirst() {return first;}publicintgetSecond() {return second;}publicintgetValue() {return value;}@OverridepublicintcompareTo(Object arg0) {return value > ((Bian) arg0).value 1: (value == ((Bian) arg0).value 0 : -1);}@Overridepublic String toString() {return "Bian [first=" + first + ",second=" + second + ",value="+ value + "]";}}classShuZu {static ArrayList<ArrayList> list = newArrayList<ArrayList>();// 存搁每一个数组中的节面的数组static ArrayList<ArrayList> bianList = newArrayList<ArrayList>();// 对付应存搁数组中的边的数组public static void check(Bian b)// 查看正在哪个数组中{if (list.size() == 0) {ArrayList<Integer> sub = new ArrayList<Integer>();sub.add(b.getFirst());sub.add(b.getSecond());list.add(sub);ArrayList<Bian> bian = new ArrayList<Bian>();bian.add(b);bianList.add(bian);return;}int first = b.getFirst();int shuyu1 = -1;int second = b.getSecond();int shuyu2 = -1;for (inti = 0; i < list.size(); i++)// 查看二个节面分别属于哪个数组{for (int m = 0; m < list.get(i).size(); m++) {if (first == (Integer) list.get(i).get(m))shuyu1 = i;if (second == (Integer) list.get(i).get(m))shuyu2 = i;}}if (shuyu1 == -1 && shuyu2 == -1)// 表示那二个节面皆不需要新加进{ArrayList<Integer> sub = new ArrayList<Integer>();sub.add(b.getFirst());sub.add(b.getSecond());list.add(sub);ArrayList<Bian> bian = new ArrayList<Bian>();bian.add(b);bianList.add(bian);}if (shuyu1 == -1 && shuyu2 != -1)// 表示有一个面已经正在数组中只把另一个加进便不妨了{list.get(shuyu2).add(first);bianList.get(shuyu2).add(b);}if (shuyu2 == -1 && shuyu1 != -1)// 表示有一个面已经正在数组中只把另一个加进便不妨了{list.get(shuyu1).add(second);bianList.get(shuyu1).add(b);}if (shuyu1 == shuyu2 && shuyu1 != -1)// 表述二个正在共一个组中会产死环{}if (shuyu1 != shuyu2 && shuyu1 != -1 && shuyu2 != -1)// 表示二个面正在分歧的组中需要合并{for (inti = 0; i < list.get(shuyu2).size(); i++) {list.get(shuyu1).add(list.get(shuyu2).get(i));}list.remove(shuyu2);for (inti = 0; i < bianList.get(shuyu2).size(); i++) { bianList.get(shuyu1).add(bianList.get(shuyu2).get(i));}bianList.get(shuyu1).add(b);bianList.remove(shuyu2);}}public static void show() {for (inti = 0; i < bianList.get(0).size(); i++) System.out.println(bianList.get(0).get(i));}}public class Test {public static void main(String[] args) { ArrayList<Bian> l = new ArrayList<Bian>(); l.add(new Bian(1,3,1));l.add(new Bian(1,2,6));l.add(new Bian(1,4,5));l.add(new Bian(2,3,5));l.add(new Bian(2,5,3));l.add(new Bian(3,4,5));l.add(new Bian(3,5,6));l.add(new Bian(3,6,4));l.add(new Bian(4,6,2));l.add(new Bian(5,6,6));Collections.sort(l);// for(inti = 0 ;i<l.size();i++)// System.out.println(l.get(i)); for (inti = 0; i < l.size(); i++) ShuZu.check(l.get(i));ShuZu.show();}}。
kruskal算法求最小生成树
数据结构课程设计Kruskal算法求最小生成树学院:班级:学号;姓名;指导老师;完成日期:目录(一)需求分析———————————(二)概要设计———————————(三)详细设计———————————(四)主函数设计—————————(五)经验体会——————————- (六)源代码及调试分析————————1、需求分析运用kruskal算法求最小生成树最短路径:①输入任意源点,求到其余顶点的最短路径。
②输入任意对顶点,求这两点之间的最短路径和所有路径。
2、概要设计首先要确定图的存储形式。
经过的题目要求的初步分析,发现该题的主要操作是路径的输出,因此采用数组(邻接矩阵)的方法构造无向图,比较方便以后的编程。
从而求得最小生成树。
3、函数详细设计(1)构造无向图本题中为了能够求得最小生成树,先要构造无向图,并且用领结矩阵的形式表现出来。
void Create(MGraph &G) //采用数组(邻接矩阵)表示法,构造无向图G。
{int i,j,k,w;char v1[10],v2[10];scanf("%d%d",&G.vexnum,&G.arcnum); //输入定点数和边数for(i=0; i<G.vexnum; i++)scanf("%s", G.vexs[i]);for(i=0; i<G.vexnum; i++) //初始化邻接矩阵{for(j=0; j<G.vexnum; j++)G.arcs[i][j] = INF;}for(k=0; k<G.arcnum; k++) //构造邻接矩阵{scanf("%s%s%d",v1,v2,&w); //输入一条边依附的顶点及权值i = Locate(G,v1); //确定v1在G中的位置j = Locate(G,v2); //确定v2在G中的位置G.arcs[i][j] = w; //弧<v1,v2>的权值G.arcs[j][i] = w; //弧<v2,v1>是权值}for(i=0; i<G.vexnum; i++){for(j=0; j<G.vexnum; j++){printf("%6d ",G.arcs[i][j]);}printf("\n");}}(2) kruskal算法。
分别利用prim算法和kruskal算法实现求图的最小生成树
/*分别利用prim算法和kruskal算法实现求图的最小生成树*/ #include<stdio.h>#include<stdlib.h>#define MaxVertexNum 12#define MaxEdgeNum 20#define MaxValue 1000typedef int Vertextype;typedef int adjmatrix[MaxVertexNum][MaxVertexNum]; typedef Vertextype vexlist[MaxVertexNum];int visited[MaxVertexNum]={0};struct edgeElem{int fromvex;int endvex;int weight;};typedef struct edgeElem edgeset[MaxVertexNum];void Creat_adjmatrix(vexlist GV,adjmatrix GA,int n,int e) {int i,j,k,w;printf("输入%d个顶点数据",n);for(i=0;i<n;i++)scanf("%d",&GV[i]);for(i=0;i<n;i++)for(j=0;j<n;j++)if(i==j) GA[i][j]=0;else GA[i][j]=MaxValue;printf("输入%d条无向带权边",e);for(k=0;k<e;k++){scanf("%d%d%d",&i,&j,&w);GA[i][j]=GA[j][i]=w;}}void Creat_edgeset(vexlist GV,edgeset GE,int n,int e) {int i,j,k,w;printf("输入%d个顶点数据",n);for(i=0;i<n;i++)scanf("%d",&GV[i]);printf("输入%d条无向带权边",e);for(k=0;k<e;k++){ scanf("%d%d%d",&i,&j,&w);GE[k].fromvex=i;GE[k].endvex=j;GE[k].weight=w;}}void output_edgeset(edgeset GE,int e){int k;for(k=0;k<e;k++)printf("%d %d %d,",GE[k].fromvex,GE[k].endvex,GE[k].weight); printf("\n");}void prim(adjmatrix GA,edgeset CT,int a,int n){int i,j,t,k,w,min,m;struct edgeElem x;for(i=0;i<n;i++)if(i<a){CT[i].fromvex=a;CT[i].endvex=i;CT[i].weight=GA[a][i];}else if(i>a){CT[i-1].fromvex=a;CT[i-1].endvex=i;CT[i-1].weight=GA[a][i];}for(k=1;k<n;k++){min=MaxValue;m=k-1;for(j=k-1;j<n-1;j++)if(CT[j].weight<min){min=CT[j].weight;m=j;}x=CT[k-1];CT[k-1]=CT[m];CT[m]=x;j=CT[k-1].endvex;for(i=k;i<n-1;i++){t=CT[i].endvex;w=GA[j][t];if(w<CT[i].weight){CT[i].weight=w;CT[i].fromvex=j;}}}}void kruskal(edgeset GE,edgeset C,int n){ int i,j,k,d;int m1,m2;adjmatrix s;for(i=0;i<n;i++){for(j=0;j<n;j++)if(i==j) s[i][j]=1;else s[i][j]=0;}k=1;d=0;while(k<n){for(i=0;i<n;i++){if(s[i][GE[d].fromvex]==1) m1=i;if(s[i][GE[d].endvex]==1) m2=i;}if(m1!=m2){C[k-1]=GE[d];k++;for(j=0;j<n;j++){s[m1][j]=s[m1][j]||s[m2][j];s[m2][j]=0;}}d++;}}void main(){int n,e;vexlist GV;adjmatrix GA;edgeset GE,C;printf("输入图的顶点数和边数:");scanf("%d%d",&n,&e);Creat_adjmatrix( GV, GA, n, e);printf("利用prim算法从0点出发求图的最小生成树:\n");prim(GA,GE,0,n);output_edgeset( GE, n-1);printf("输入图的顶点数和边数:");scanf("%d%d",&n,&e);Creat_edgeset( GV,GE,n, e);printf("利用kruskal算法从0点出发求图的最小生成树:\n");kruskal( GE, C, n);output_edgeset( C, n-1);}最小生成树(prim算法和kruskal算法)收藏最小生成树(prim算法)用最小生成树的解决的经典问题:若要在n个城市间建设通信网路,给出任意两个城市的距离和每米通信网路的造价,问怎样设计网络可以使网路的造价最小。
克鲁斯卡尔(Kruskal)算法求无向网的最小生成树数据结构报告
数据结构上机报告(1) 姓名:张可心学号:14030188030 班级:1403018一、题目描述用克鲁斯卡尔(Kruskal)算法求无向网的最小生成树,分析你的算法的时空复杂度,必须有过程说明。
输入:输入数据第一行为两个正整数n和m,分别表示顶点数和边数。
后面紧跟m行数据,每行数据是一条边的信息,包括三个数字,分别表示该边的两个顶点和边上的权值。
输出:按顺序输出Kruskal算法求得的最小生成树的边集,每行一条边,包括三个数字,分别是该边的两个顶点和边上的权值,其中第一个顶点的编号应小于第二个顶点的编号。
示例输入8 111 2 31 4 51 6 182 4 72 5 63 5 103 8 204 6 154 7 115 7 85 8 12示例输出1 2 31 4 52 5 65 7 83 5 105 8 124 6 15二、解题思路(1)假定每对顶点表示图的一条边,每条边对应一个权值;(2)输入每条边的顶点和权值;(3)输入每条边后,计算出最小生成树;(4)打印最小生成树边的顶点及权值。
三、源代码#include<stdio.h>#include<stdlib.h>typedef struct {int a,b,value;}node;int stcmp(const void *p,const void *q){node *a=(node *)p;node *b=(node *)q;if(a->value>b->value){return 1;}else if(a->value==b->value){return 0;}else{return -1;}}int root(int a,int *b){for(;a!=b[a];a=b[a]);return a;}bool isgroup(int a,int b,int *c){if(root(a,c)==root(b,c))return true;return false;}void add(int a,int tob,int *c){c[root(a,c)]=root(tob,c);}int main (){int n,m;scanf("%d %d",&n,&m);node no[m];for(int u=0;u<m;u++){scanf("%d",&(no[u].a));scanf("%d",&(no[u].b));scanf("%d",&(no[u].value));}qsort(no,m,sizeof(no[0]),stcmp);int bcj[n+1];for(int u=1;u<=n;u++){bcj[u]=u;}int i=0;int cc=n;for(;i<m;i++){if(!isgroup(no[i].a,no[i].b,bcj)){add(no[i].a,no[i].b,bcj);cc--;printf("%d %d %d\n",no[i].a,no[i].b,no[i].value);}if(cc==1)break;}return 0;}四、运行结果。
kruskal算法求最小生成树
kruskal算法求最小生成树课题:用kruskal算法求最小生成树。
编译工具:Visual Studio 2017kruskal算法基本思想:先构造一个只含n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集E中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。
依次类推,直到森林中只有一棵树,也即子图中含有n-1 条边为止。
问题:按如下连通图用kruskal算法求最小生成树。
程序源码:#include <iostream>#include <algorithm>using namespace std;const int N = 100;int nodeset[N];int n, m;struct Edge { //定义结构体.int u;int v;int w;}e[N*N];bool comp(Edge x, Edge y) { //配合sort()方法对权值进行升序。
return x.w < y.w;}void Init(int n) //对集合号nodeset数组进行初始化. {for (int i = 1; i <= n; i++)nodeset[i] = i;}int Merge(int a, int b) //将e[i].u结点传递给a; e[i].v结点传递给b. {int p = nodeset[a]; //p为a结点的集结号,int q = nodeset[b]; //q为b 结点的集结号.if (p == q) return 0; //判断结点间是否回环。
若两个结点的集结号相同,则不操作,直接返回。
for (int i = 1; i <= n; i++)//若两个结点的集结号不相同,检查所有结点,把集合号是q的改为p.{if (nodeset[i] == q)nodeset[i] = p;}return 1;}int Kruskal(int n){int ans = 0;for (int i = 1; i<=m; i++)if (Merge(e[i].u, e[i].v)){cout << "A结点:" << e[i].u << "一>B结点:" << e[i].v << endl; //输出满足条件的各结点ans += e[i].w;n--;if (n == 1)return ans;}return 0;}int main() {cout << "输入总结点数(n)和总边数(m):" << endl;cin >> n >> m;Init(n);cout << "输入结点数(u),(v)和权值(w):" << endl;for (int i = 1; i <= m; i++)cin >> e[i].u >> e[i].v >> e[i].w;sort(e+1, e + m+1, comp);int ans = Kruskal(n);cout << "最小的花费是:" << ans << endl;return 0;}源码流程解析:(1)在main()中,输入结点数n与边m,n=7,m=12。
最小生成树算法(krukal和prim算法)
=========================================================Krukal算法实现代码==========================================================function [out,len]=kruskal(map)%求最小生成树算法,通过kruskal算法求最优树,并给出相应图像.%用法:% 首先输入矩阵:% map=[起点1 终点1 边长1;起点2 终点2 边长2;............;起点n 终点n 边长n]% 再用[out,len]=kruskal(map)求最优树%参数说明% map----3列邻接矩阵,每行表示一条边.第一列表示起点,第二列表示终点,第三列表示边长% out---输出边阵:[起点终点]% len---输出最优树的总长度%%例如% clear;map=[1 2 30;2 4 5;2 5 50;3 2 6;4 3 1;1 4 20;1 5 30]% [out,len]=kruskal(map)%%See also DIJKSTRA,LPINT,DP,BNBGUI,BNB18,%By S. J. Lu 2000mx=0;[m,n]=size(map);mx=max(max(map(:,1:2)));op=inf.*ones(mx,mx);for i=1:mop(map(i,1),map(i,2))=map(i,3);op(map(i,2),map(i,1))=map(i,3);end[out,len]=krusk(op);out=out';% 画图close;set(gcf,'numbertitle','off');set(gcf,'name','Kruskal');set(gca,'visible','off');axis square;hold on;b=linspace(0,2*pi,mx+1);b1=10*sin(b);b2=10*cos(b);plot(b1,b2,'ko');hh=char(49:48+mx);for i=1:mxtext(b1(i)+1,b2(i),hh(i));end;mapfor j=1:mfor i=1:2c1(i)=b1(map(j,i));c2(i)=b2(map(j,i));end;plot(c1,c2,':');end;k1=length(out);for i=1:k1for j=1:2d1(j)=b1(out(i,j));d2(j)=b2(out(i,j));endh=plot(d1,d2,'r');set(h,'linewidth',2);endlegend(h,'粗线为最优树');hold off========================================================= 上面的示例的执行结果为========================================================= >>map =[1 2 42 3 83 4 73 8 22 9 114 5 94 6 145 6 103 6 46 7 27 8 6;7 9 11 9 8];>>[out,len]=kruskal(map)out =7 93 86 71 23 63 41 94 5len =37。
java实现最小生成树的prim算法和kruskal算法
java实现最⼩⽣成树的prim算法和kruskal算法在边赋权图中,权值总和最⼩的⽣成树称为最⼩⽣成树。
构造最⼩⽣成树有两种算法,分别是prim算法和kruskal算法。
在边赋权图中,如下图所⽰:在上述赋权图中,可以看到图的顶点编号和顶点之间邻接边的权值,若要以上图来构建最⼩⽣成树。
结果应该如下所⽰:这样构建的最⼩⽣成树的权值总和最⼩,为17在构建最⼩⽣成树中,⼀般有两种算法,prim算法和kruskal算法在prim算法中,通过加⼊最⼩邻接边的⽅法来建⽴最⼩⽣成树算法。
⾸先构造⼀个零图,在选⼀个初始顶点加⼊到新集合中,然后分别在原先的顶点集合中抽取⼀个顶点,使得构成的边为权值最⼩,然后将该笔边加⼊到图中,并将抽出的顶点加⼊到新集合中,重复这个过程,知道新集合等于原先的集合。
代码⼀:(java)1/**2 * 最⼩⽣成树的prim算法3 * @author liuy4*/5public class Prim {67public static void prim(int num, float[][] weight) { //num为顶点数,weight为权8float[] lowcost = new float[num + 1]; //到新集合的最⼩权910int[] closest = new int[num + 1]; //代表与s集合相连的最⼩权边的点1112boolean[] s = new boolean[num + 1]; //s[i] == true代表i点在s集合中1314 s[1] = true; //将第⼀个点放⼊s集合1516for(int i = 2; i <= num; i++) { //初始化辅助数组17 lowcost[i] = weight[1][i];18 closest[i] = 1;19 s[i] = false;20 }2122for(int i = 1; i < num; i++) {23float min = Float.MAX_VALUE;24int j = 1;25for(int k = 2; k <= num; k++) {26if((lowcost[k] < min) && (!s[k])) {//根据最⼩权加⼊新点27 min = lowcost[k];28 j = k;29 }30 }3132 System.out.println("加⼊点" + j + ". " + j + "---" + closest[j]);//新加⼊点的j和与j相连的点3334 s[j] = true;//加⼊新点j3536for(int k = 2; k <= num; k++) {37if((weight[j][k] < lowcost[k]) && !s[k]) {//根据新加⼊的点j,求得最⼩权38 lowcost[k] = weight[j][k];39 closest[k] = j;40 }41 }42 }43 }4445public static void main(String[] args) {46// ①47// / | /48// 6 1 549// / | /50// ②-5--③--5--④51// / // /52// 3 6 4 253//////54// ⑤--6-⑥55//最⼩⽣成树为:56// ①57// |58// 159// |60// ②-5--③④61// / / /62// 3 4 263// / //64// ⑤⑥65//66float m = Float.MAX_VALUE;67float[][] weight = {{0, 0, 0, 0, 0, 0, 0},68 {0, m, 6, 1, 5, m, m},69 {0, 6, m, 5, m, 3, m},70 {0, 1, 5, m, 5, 6, 4},71 {0, 5, m, 5, m, m, 2},72 {0, m, 3, 6, m, m, 6},73 {0, m, m, 4, 2, 6, m}};//上图的矩阵74 prim(weight.length - 1, weight);75//加⼊点3. 3---176//加⼊点6. 6---377//加⼊点4. 4---678//加⼊点2. 2---379//加⼊点5. 5---280 }81 }View Code代码⼆:(java)1package最⼩⽣成树;2/*3 * 最⼩⽣成树prim算法,加⼊最⼩邻接边⽣成最⼩⽣成树。
Kruskal算法(三)之Java详解
Kruskal算法(三)之Java详解前⾯分别通过C和C++实现了克鲁斯卡尔,本⽂介绍克鲁斯卡尔的Java实现。
⽬录1.2.3.4.5.6.更多内容:最⼩⽣成树在含有n个顶点的连通图中选择n-1条边,构成⼀棵极⼩连通⼦图,并使该连通⼦图中n-1条边上权值之和达到最⼩,则称其为连通⽹的最⼩⽣成树。
例如,对于如上图G4所⽰的连通⽹可以有多棵权值总和不相同的⽣成树。
克鲁斯卡尔算法介绍克鲁斯卡尔(Kruskal)算法,是⽤来求加权连通图的最⼩⽣成树的算法。
基本思想:按照权值从⼩到⼤的顺序选择n-1条边,并保证这n-1条边不构成回路。
具体做法:⾸先构造⼀个只含n个顶点的森林,然后依权值从⼩到⼤从连通⽹中选择边加⼊到森林中,并使森林中不产⽣回路,直⾄森林变成⼀棵树为⽌。
克鲁斯卡尔算法图解以上图G4为例,来对克鲁斯卡尔进⾏演⽰(假设,⽤数组R保存最⼩⽣成树结果)。
第1步:将边<E,F>加⼊R中。
边<E,F>的权值最⼩,因此将它加⼊到最⼩⽣成树结果R中。
第2步:将边<C,D>加⼊R中。
上⼀步操作之后,边<C,D>的权值最⼩,因此将它加⼊到最⼩⽣成树结果R中。
第3步:将边<D,E>加⼊R中。
上⼀步操作之后,边<D,E>的权值最⼩,因此将它加⼊到最⼩⽣成树结果R中。
第4步:将边<B,F>加⼊R中。
上⼀步操作之后,边<C,E>的权值最⼩,但<C,E>会和已有的边构成回路;因此,跳过边<C,E>。
同理,跳过边<C,F>。
将边<B,F>加⼊到最⼩⽣成树结果R中。
第5步:将边<E,G>加⼊R中。
上⼀步操作之后,边<E,G>的权值最⼩,因此将它加⼊到最⼩⽣成树结果R中。
第6步:将边<A,B>加⼊R中。
上⼀步操作之后,边<F,G>的权值最⼩,但<F,G>会和已有的边构成回路;因此,跳过边<F,G>。
数据结构Kruskal算法求解最小生成树
数据结构Kruskal算法求解最小生成树#include<stdio.h>#include<stdlib.h>#include<malloc.h>#define MAX 100struct Node{int vertex1;int vertex2;int weight;struct Node *next;};typedef struct Node * Edge;Edge head = NULL;int visited[MAX];Edge read(){int v1, v2, w;Edge newNode = NULL, pointer = NULL;while(1){scanf("%d %d %d", &v1, &v2, &w);if(v1 == -1 || v2 == -1 || w == -1)break;newNode = (Edge)malloc(sizeof(struct Node));newNode->vertex1 = v1;newNode->vertex2 = v2;newNode->weight = w;newNode->next = NULL;pointer = head;if(pointer == NULL)head = newNode;else{if(newNode->weight < pointer->weight){newNode->next = pointer;head = newNode;}else{while(pointer != NULL && pointer->next != NULL){if(pointer->weight < newNode->weight && newNode->weight < pointer->next->weight){newNode->next = pointer->next;pointer->next = newNode;break;}pointer = pointer->next;}pointer->next = newNode;}}}return head;}void printLink(Edge edge){Edge pointer = edge;printf("\n\n图中所有边按权值递增的排序如下: \n");while(pointer != NULL){printf("[%d %d]", pointer->vertex1, pointer->vertex2);printf("(%d)",pointer->weight);if(pointer->next != NULL)printf(" ==> ");pointer = pointer->next;}printf("\n");}void kruskal(Edge edge, int vexnum){int visitedEdgeNum = 0, weight = 0;printf("\n最小生成树的路径为: \n");while(visitedEdgeNum < vexnum){if(visited[edge->vertex1] == 0 || visited[edge->vertex2] == 0){ printf("[%d %d]", edge->vertex1, edge->vertex2);printf("(%d) ",edge->weight);weight += edge->weight; visitedEdgeNum++;visited[edge->vertex1] = 1;visited[edge->vertex2] = 1;}edge = edge->next;if(edge == NULL){break;}}printf("\n\n最短路径长度为:%d \n\n", weight);}void main(){int vexnum, i;Edge edge = NULL;printf("请输入定点个数、各顶点和权值:\n输入形式如下:n i j w ... -1 -1 -1\nn 表示图的顶点个数,i j w 表示从顶点i 到顶点j 的权为w 的一条边,均以-1结尾。
kruskal算法java实现
kruskal算法java实现Kruskal算法是一种用于求解最小生成树的算法。
它是以其发明者Joseph Kruskal的名字命名的。
在这篇文章中,我们将介绍Kruskal算法的原理和Java实现。
我们来了解一下最小生成树的概念。
在一个带权无向图中,最小生成树是指一个连通子图,它包含了原图中的所有顶点,并且边的权值之和最小。
最小生成树的应用非常广泛,比如在电力传输、通信网络、城市规划等领域。
Kruskal算法的基本思想是从图中选择权值最小的边,并且保证这条边不会形成环路,然后不断重复这个过程,直到生成树中包含了所有顶点为止。
下面我们来详细讲解一下Kruskal算法的步骤。
我们需要将图中的边按照权值从小到大进行排序。
然后,我们从权值最小的边开始,依次判断这条边的两个顶点是否属于同一个连通分量。
如果不属于同一个连通分量,则将这条边加入生成树中,并且将这两个顶点合并到同一个连通分量中。
如果属于同一个连通分量,则舍弃这条边,继续判断下一条边。
为了实现Kruskal算法,我们需要使用并查集这个数据结构来管理连通分量。
并查集是一种用于解决集合合并与查询问题的数据结构,它主要包含两个操作:合并和查询。
合并操作用于将两个不同的集合合并为一个集合,查询操作用于判断两个元素是否属于同一个集下面是Kruskal算法的Java实现:```javaimport java.util.Arrays;class Edge implements Comparable<Edge> { int src, dest, weight;public int compareTo(Edge edge) {return this.weight - edge.weight;}}class Graph {int V, E;Edge[] edges;Graph(int V, int E) {this.V = V;this.E = E;edges = new Edge[E];for (int i = 0; i < E; ++i) {edges[i] = new Edge();}int find(int[] parent, int i) {if (parent[i] == -1) {return i;}return find(parent, parent[i]);}void union(int[] parent, int x, int y) { int xset = find(parent, x);int yset = find(parent, y);parent[xset] = yset;}void kruskalMST() {Edge[] result = new Edge[V];int e = 0;int i = 0;Arrays.sort(edges);int[] parent = new int[V];Arrays.fill(parent, -1);while (e < V - 1) {Edge next_edge = edges[i++];int x = find(parent, next_edge.src);int y = find(parent, next_edge.dest);if (x != y) {result[e++] = next_edge;union(parent, x, y);}}System.out.println("最小生成树的边:");for (i = 0; i < e; ++i) {System.out.println(result[i].src + " - " + result[i].dest + ": " + result[i].weight);}}}public class KruskalAlgorithm {public static void main(String[] args) {int V = 4;int E = 5;Graph graph = new Graph(V, E);graph.edges[0].src = 0;graph.edges[0].dest = 1;graph.edges[0].weight = 10;graph.edges[1].src = 0;graph.edges[1].dest = 2;graph.edges[1].weight = 6;graph.edges[2].src = 0;graph.edges[2].dest = 3;graph.edges[2].weight = 5;graph.edges[3].src = 1;graph.edges[3].dest = 3;graph.edges[3].weight = 15;graph.edges[4].src = 2;graph.edges[4].dest = 3;graph.edges[4].weight = 4;graph.kruskalMST();}}```在这个示例中,我们创建了一个具有4个顶点和5条边的图。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Kruskal算法求最小生成树(JA V A)
代码:
package homework;
import java.util.Scanner;
import java.util.Arrays;
import java.util.ArrayList;
class Edge {
public int start;//始边
public int end;//终边
public double cost;//权重
}
public class MinSpanningTree_Kruskal{
private static int MAX = 100;
private ArrayList<Edge> edge = new ArrayList<Edge>();//整个图的边
private ArrayList<Edge> target = new ArrayList<Edge>();//目标边,最小生成树private int[] parent = new int[MAX];//标志所在的集合
private static double INFINITY = 99999999.99;//定义无穷大
private double mincost = 0.0;//最小成本
private int n;//结点个数
public MinSpanningTree_Kruskal(){}
public static void main(String args[]){
MinSpanningTree_Kruskal sp = new MinSpanningTree_Kruskal();
sp.init();
sp.kruskal();
sp.print();
}//初始化
public void init(){
Scanner scan = new Scanner(System.in);
int p,q;
double w;
System.out.println("请输入结点个数:");
n = scan.nextInt();
System.out.println("请输入各条边及权值(每次输入一组数据按回车确认," +
"最后输入-1 -1 -1 结束输入过程)");
while(true){
p = scan.nextInt();
q = scan.nextInt();
w = scan.nextDouble();
if(p < 0 || q < 0 || w < 0){
break;
}
Edge e = new Edge();
e.start = p; e.end = q; e.cost = w;
edge.add(e);
}
mincost = 0.0;
for(int i = 1; i <= n; ++i){
parent[i] = i;
}
}//集合合并
public void union(int j, int k){
for(int i = 1; i <= n; ++i){
if(parent[i] == j){
parent[i] = k;
}
}
}//prim算法主体
public void kruskal(){
//找剩下的n-2条边
int i = 0;
while(i < n-1 && edge.size() > 0){
//每次取一最小边,并删除
double min = INFINITY;
int tag = 0;
Edge tmp = null;
for(int j = 0; j < edge.size(); ++j){
Edge tt = edge.get(j);
if(tt.cost < min){
min = tt.cost;
tmp = tt;
}
}
int jj = parent[tmp.start];
int kk = parent[tmp.end];
//去掉环
if(jj != kk){
++i;
target.add(tmp);
mincost += tmp.cost;
union(jj,kk);
}
edge.remove(tmp);
}
if(i != n-1){
System.out.println("没有最小生成树");
System.exit(0);
}
}//打印结果
public void print(){
double sum=0;
System.out.println("最小生成树:");
for(int i = 0; i < target.size(); ++i){
Edge e = target.get(i);
System.out.println("第" + (i+1) + "条边: " + e.start + "---" + e.end
+ " 权值:" + e.cost);
sum=sum+e.cost;
}
System.out.println("最小生成树的权值:" + sum);
}
}
调试结果:。