kruskal算法求最小生成树

合集下载

求无向图的最小生成树算法——Prim与Kruskal

求无向图的最小生成树算法——Prim与Kruskal

求无向图的最小生成树算法——Prim与Kruskal一.Prim算法1.算法思想对于图G=(V,E),用Prim算法求最小生成树T=(S,TE)的流程如下① 初始化:设S、TE为空集,任选节点K加入S。

② 选取一条权值最小的边(X,Y),其中X∈S,且not (Y∈S)即,选取一条权值最小的、连接着S中一点与S外一点的边。

将Y加入S中,边(X,Y)加入TE中重复② 直到V=S即所有G中的点都在S中,此时的T为G的最小生成树。

由此流程可见,Prim算法求最小生成树时任何时候的T都是一颗树。

2.实现显然,Prim算法的主要运行时间花在过程②的选边中。

看起来复杂度是O(VE)=O(V^3)不是么,效率也太低了吧……为了比较快速地选边,我们用两个数组lowcost、closest动态地维护每一个点到S的最短距离。

在某一状态下,lowcost[i]表示所有与i相连且另一端点在S中的边中的权值最小值,closest[i]表示在S中且与i相连的点中与i之间距离最小的点。

显然,lowcost[i]=w(i,closest[i])。

需要注意的是两个数组记录的都是边而不是路径。

若i没有边直接连向S,则lowcost[i]=∞。

另外,若i已在S 中,则lowcost[i]=0。

设出发点为x。

初始时对于任意k∈V,closest[k]=x,lowcost[k]=w(k,x)【w(i,j)表示i、j间的距离。

初始化时,若两点间没有边则w(i,j)赋为一个足够大的整数(如maxint),并且所有点到自身的距离赋为0,即w(i,i)=0】每一次找出lowcost中不为0的最小值lowcost[i],然后把i加入S(即lowcost[i]:=0),然后对于图中所有点k,若w(k,i)<lowcost[k],则把lowcost[k]赋为w(k,i),把closest[k]赋为i。

【由于s中所有点的lowcost都为0,所以只影响到s以外的点】以上操作重复|V|-1次结束。

Kruskal克鲁斯卡尔最小生成树算法(贪心算法)

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算法)

最小生成树(Kruskal算法)

三、方案解决:
在本题中我们将采用 Kruskal 算法来构造最小生成树。 从题目所给赋权图中我们可以得到该图的邻接矩阵为:
⎡ 0 20 0 0 0 23 1 ⎤ ⎢20 0 15 0 0 0 4 ⎥ ⎢ ⎥ ⎢ 0 15 0 3 0 0 9 ⎥ ⎢ ⎥ G = ⎢ 0 0 3 0 17 0 16 ⎥ ⎢ 0 0 0 17 0 28 25⎥ ⎢ ⎥ ⎢ 23 0 0 0 28 0 36⎥ ⎢ 1 4 9 16 25 36 0 ⎥ ⎣ ⎦
-3-
6.选择造价第五小的序号为 5 的边,即 S 23 ,由于加入后边 S 23 , S 27 , S37 将构成回路,因此 舍弃该边 如图所示:
7.选择造价第六小的序号为 6 的边,即 S 47 ,由于加入后边 S34 , S37 , S 47 将构成回路,因此 舍弃该边 如图所示:
8.选择造价第七小的序号为 7 的边,即 S 45 ,加入 T 中,此时 T={{6},{ S17 , S34 , S 27 , S37 ,
S 45 , S16 }},Cost=34+23=57
如图所示:
11.算法结束 此时,所有顶点已包含在树中,整棵最小生成树已经构造完成。即应该在城市{(1,7) , (2,7) , (3,7) , (3,4) , (4,5) , (1,6)}之间建造通信道路,可使得城市间相互通信又造价费 用最小,此时可以得到其最小的费用为 57 万元
-7-
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[n] = m; printf("< %d, %d > %d\n", edges[i].begin, edges[i].end, edges[i].weight); Mincost+=edges[i].weight; } } printf("使各城市间能够通信的最小费用为:Mincost=%d\n",Mincost); } int Find(int *parent, int f) { while ( parent[f] > 0) { f = parent[f]; } return f; }

② kruskal最小生成树算法的定义和实现

② kruskal最小生成树算法的定义和实现

Krskal最小生成树算法是一种用来解决图论中最小生成树问题的算法。

它采用了一种贪心的策略,即每一步都选择权值最小的边,并且保证选择的边不会构成环,直到生成一棵最小生成树为止。

1. 算法的定义kruskal最小生成树算法的定义如下:输入:一个连通无向图G=(V,E),其中V是顶点集合,E是边的集合,每条边都有一个权值。

输出:G的最小生成树算法步骤:① 将图G的所有边按照权值从小到大进行排序。

② 初始化一个空的边集合T,该集合用来存放最小生成树的边。

③ 依次遍历排序后的边集合,对于每一条边e=(u,v),如果将该边添加到T中不会构成环,则将其添加到T中。

④ 重复步骤③,直到T中的边数等于V-1为止,此时T就是G的最小生成树。

2. 算法的实现下面是kruskal最小生成树算法的具体实现过程:```pythonclass UnionFind:def __init__(self, n):self.parent = [i for i in range(n)]def find(self, x):if self.parent[x] != x:self.parent[x] = self.find(self.parent[x]) return self.parent[x]def union(self, x, y):root_x = self.find(x)root_y = self.find(y)if root_x != root_y:self.parent[root_x] = root_ydef kruskal(graph):edges = []for u in range(len(graph)):for v in range(u+1, len(graph)):if graph[u][v] != 0:edges.append((u, v, graph[u][v])) edges.sort(key=lambda x: x[2])n = len(graph)result = []uf = UnionFind(n)for edge in edges:u, v, weight = edgeif uf.find(u) != uf.find(v):uf.union(u, v)result.append((u, v, weight))if len(result) == n - 1:breakreturn result```以上代码实现了kruskal最小生成树算法,其中使用了UnionFind类来实现并查集的功能,以判断是否构成环。

c语言数据结构kruskal算法两种构造最小生成树算法

c语言数据结构kruskal算法两种构造最小生成树算法

c语言数据结构kruskal算法两种构造最小生成树算法1. 引言1.1 概述本篇文章将讨论C语言数据结构中的Kruskal算法以及它的两种构造最小生成树的方法。

数据结构是计算机科学中至关重要的概念,它用于组织和存储数据以便于使用和操作。

C语言是一种广泛应用于系统开发和嵌入式软件的编程语言,而Kruskal算法则是解决图论中最小生成树问题的一种有效方法。

1.2 文章结构本文共分为五个部分。

首先,我们将介绍C语言中的数据结构,包括其概念、在C语言中的实现以及在算法中应用的重要性。

接下来,我们将对Kruskal算法进行简要介绍,包括最小生成树的概念和应用场景、Kruskal算法原理及思路以及详细步骤解析。

然后,我们将探讨Kruskal算法的两种构造最小生成树的方法:按边权重顺序遍历并加入最小生成树中和使用并查集维护连通性信息并进行判断和合并操作。

最后,我们将总结评估这两种方法,并讨论适用情景与选择依据。

文章最后将给出结论与总结,并对该算法的效率、应用案例以及未来的可扩展和改进方向进行分析。

1.3 目的本文旨在深入介绍C语言数据结构中Kruskal算法的两种构造最小生成树的方法,并对它们进行比较与选择依据分析。

通过阅读本文,读者将能够理解数据结构在算法中的应用、掌握Kruskal算法的原理和步骤,并了解如何选择合适的构造最小生成树方法。

此外,本文还将讨论该算法的效率、实际应用案例以及未来可能的发展方向,以便读者更全面地了解该算法并从中受益。

2. C语言数据结构简介:2.1 数据结构概念数据结构是计算机存储、组织和管理数据的方式。

它涉及到如何将不同类型的数据元素组合在一起,以便有效地进行操作和处理。

常见的数据结构包括数组、链表、栈、队列、树等。

2.2 C语言中的数据结构C语言提供了基本的数据类型,如整型、浮点型和字符型等,同时还支持用户自定义的数据结构。

通过使用struct关键字可以定义自己的复合类型,其中可以包含多个不同类型的成员变量。

Kruskal算法计算最小生成树(java)

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算法求最小生成树

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算法是一种按照网中边的权值递增的顺序构造最小生成树的方法。

用Kruskal算法求无向图的最小生成树

用Kruskal算法求无向图的最小生成树

用Kruskal算法求无向图的最小生成树该图用邻接矩阵表示,邻接表原理与之相同。

可以指出的是,对于有向图,算法可以做得更加简单,因为对无向图的“回边”情况的处理比有向图回边情况的处理要复杂一些。

图1:输入示例图二:输入时若两点之间没有公共边,则将权值设置为-1。

程序设置处理的最大点数为10。

图三:注意到Kruskal算法的解答结果有时候不是唯一的,这个结果和对图遍历时的顺序有关,但是必需注意的是所有的最小生成树其网络代价和是一样的。

下面是源代码:/* Kruskal.cCopyright (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;int FindCircle(int,int,int,int);int main(){int path[maxver][2],used[maxver][maxver];int i,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!Please reinput!\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[i][0]=v1;path[i][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 to vertex %d\n",i+1,path[i][0]+1,path[i][1]+1); }return 1;}int FindCircle(int start,int begin,int times,int pre){ /* to judge whether a circle is produced*/int i;for(i=0;i<times;i++)if(touched[begin][i]==1){if(i==start&&pre!=start){circle=1;return 1;break;}elseif(pre!=i)FindCircle(start,i,times,begin); elsecontinue;}return 1;}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define maxn 110 //最多点个数
int n, m; //点个数,边数
int parent[maxn]; //父亲节点,当值为-1时表示根节点
int ans; //存放最小生成树权值
struct eage //边的结构体,u、v为两端点,w为边权值
{
int u, v, w;
}EG[5010];
bool cmp(eage a, eage b) //排序调用
{
return a.w < b.w;
}
int Find(int x) //寻找根节点,判断是否在同一棵树中的依据
{
if(parent[x] == -1) return x;
return Find(parent[x]);
}
void Kruskal() //Kruskal算法,parent能够还原一棵生成树,或者森林{
memset(parent, -1, sizeof(parent));
sort(EG+1, EG+m+1, cmp); //按权值将边从小到大排序
ans = 0;
for(int i = 1; i <= m; i++) //按权值从小到大选择边
{
int t1 = Find(EG[i].u), t2 = Find(EG[i].v);
if(t1 != t2) //若不在同一棵树种则选择该边,合并两棵树
{
ans += EG[i].w;
parent[t1] = t2;
printf("最小生成树加入的边为:%d %d\n",EG[i].u,EG[i].v);
}
}
}
int main()
{
printf("输入顶点数和边数:");
while(~scanf("%d%d", &n,&m))
{
for(int i = 1; i <= m; i++)
scanf("%d%d%d", &EG[i].u, &EG[i].v, &EG[i].w);
Kruskal();
printf("最小生成树权值之和为:%d\n", ans);
}
return 0;
}。

相关文档
最新文档