Prim算法和Kruskal算法(图论中的最小生成树算法)
最小生成树在一个图中可以有多个,但是如果一个图中边的权值互不相同的话,那么最小生成树只可能存在一个,用反证法很容易就证明出来了。
当然最小生成树也是一个图中包含所有节点的权值和最低的子图。
在一个图中权值最小的那个边一定在最小生成树中,如果一个图包含环,环中权值最大的边一定不在最小生成树中,还有就是连接图的任意两个划分的边中权值最短的那一条一定在最小生成树中。
下面介绍两个算法。
Prim算法
Prim算法就是以任意一个点为源点,将所有点分为两组,一组是已经在最小生成树上的点,另一组是还未在最小生成树上的点,最初只有源点在最小生成树上。图中一定存在这样的边:它们的一个顶点在最小生成树上,另一点不在最小生成树上,将这些边中权值最短的那一条以及所连接的点加入最小生成树,继续循环直至所有点都在最小生成树上为止。在具体实现中,可以用一个包含所有节点的辅助数组来记录,这个数组的每个元素包含该点到最小生成树的距离最短的边的权值和这条边的另一个端点(也就是已经在树上的那个点),如果这个点已经在最小生成树上了,权值就为0,这样每次往最小生成树上新加一个点的时候,就去检查所有与它相邻的点,如果那些相邻的点到新加的的距离小于到原先树中点的距离的话,就更新那些点在辅助数组中的信息。
int Prim(struct Graph *G, struct Vertex vertex_list[ ], int S){ ; ; i < G->vertex_num; i++){ if(S != i){ vertex_list[i].adjacent_vertex = S; vertex_list[i].low_cost = G->map[S][i]; } else{ vertex_list[i].adjacent_vertex = -; vertex_list[i].low_cost = ; } } ; j < G->vertex_num; j++){ min_cost = Infinity; ; i < G->vertex_num; i++){ != vertex_list[i].low_cost&&min_cost > vertex_list[i].low_cost){ min_cost = vertex_list[i].low_cost; tmp_index = i; } } sum += min_cost; vertex_list[tmp_index].low_cost = ; ; i < G->vertex_num; i++){ != vertex_list[i].low_cost&&vertex_list[i].low_cost > G->map[tmp_index][i]){ vertex_list[i].adjacent_vertex = tmp_index; vertex_list[i].low_cost = G->map[tmp_index][i]; } } } return sum; }
Kruskal算法
Kruskal算法就是将所有边按权值从小到大加入最小生成树中,并且保证不形成环,确定不形成环的方式类似于并查集。
int Kruskal(struct Graph *G){ , i, j, sum = , tmp, tmp_1, tmp_2; int vertex_list[G->vertex_num]; struct Edge edge_list[G->edge_num]; ; i < G->vertex_num; i++){ vertex_list[i] = i; } ; i < G->vertex_num; i++){ for(j = i; j < G->vertex_num; j++){ if(Infinity != G->map[i][j]){ edge_list[index].start = i; edge_list[index].end = j; edge_list[index].weight = G->map[i][j]; index++; } } } qsort(edge_list, G->edge_num, sizeof(struct Edge), comp); ; i < G->edge_num; i++){ if(vertex_list[edge_list[i].start] != vertex_list[edge_list[i].end]){ ; j < G->vertex_num; j++){ if(vertex_list[j] == vertex_list[edge_list[i].end]){ vertex_list[j] = vertex_list[edge_list[i].start]; } } sum += edge_list[i].weight; printf("%d %d\n", edge_list[i].start, edge_list[i].end); } } return sum; }
下面是完整代码,我也没怎么测过。
// // main.c // Minimum Spanning Tree // // Created by 余南龙 on 2016/11/27. // Copyright © 2016年 余南龙. All rights reserved. // #include <stdio.h> #include <stdlib.h> #define MAXV 100 #define Infinity 10000000 struct Vertex{ int adjacent_vertex; int low_cost; }; struct Edge{ int start; int end; int weight; }; struct Graph{ int map[MAXV][MAXV]; int edge_num; int vertex_num; }; int comp(const void *a, const void *b){ struct Edge *pa = (struct Edge *)a; struct Edge *pb = (struct Edge *)b; if(pa->weight < pb->weight){ ; } else{ ; } } int Prim(struct Graph *G, struct Vertex vertex_list[ ], int S){ ; ; i < G->vertex_num; i++){ if(S != i){ vertex_list[i].adjacent_vertex = S; vertex_list[i].low_cost = G->map[S][i]; } else{ vertex_list[i].adjacent_vertex = -; vertex_list[i].low_cost = ; } } ; j < G->vertex_num; j++){ min_cost = Infinity; ; i < G->vertex_num; i++){ != vertex_list[i].low_cost&&min_cost > vertex_list[i].low_cost){ min_cost = vertex_list[i].low_cost; tmp_index = i; } } sum += min_cost; vertex_list[tmp_index].low_cost = ; ; i < G->vertex_num; i++){ != vertex_list[i].low_cost&&vertex_list[i].low_cost > G->map[tmp_index][i]){ vertex_list[i].adjacent_vertex = tmp_index; vertex_list[i].low_cost = G->map[tmp_index][i]; } } } return sum; } int Kruskal(struct Graph *G){ , i, j, sum = , tmp, tmp_1, tmp_2; int vertex_list[G->vertex_num]; struct Edge edge_list[G->edge_num]; ; i < G->vertex_num; i++){ vertex_list[i] = i; } ; i < G->vertex_num; i++){ for(j = i; j < G->vertex_num; j++){ if(Infinity != G->map[i][j]){ edge_list[index].start = i; edge_list[index].end = j; edge_list[index].weight = G->map[i][j]; index++; } } } qsort(edge_list, G->edge_num, sizeof(struct Edge), comp); ; i < G->edge_num; i++){ if(vertex_list[edge_list[i].start] != vertex_list[edge_list[i].end]){ ; j < G->vertex_num; j++){ if(vertex_list[j] == vertex_list[edge_list[i].end]){ vertex_list[j] = vertex_list[edge_list[i].start]; } } sum += edge_list[i].weight; printf("%d %d\n", edge_list[i].start, edge_list[i].end); } } return sum; } void Init(struct Graph *G){ int i, j, start, end, weight; scanf("%d%d", &(G->edge_num), &(G->vertex_num)); ; i < G->vertex_num; i++){ ; j < G->vertex_num; j++){ G->map[i][j] = Infinity; } } ; i < G->edge_num; i++){ scanf("%d%d%d", &start, &end, &weight); G->map[start][end] = G->map[end][start] = weight; } } void Output(struct Vertex vertex_list[ ], int size){ int i; ; i < size; i++){ printf("%d %d\n", i, vertex_list[i].adjacent_vertex); } } int main(){ struct Graph G; struct Vertex *vertex_list; int sum; Init(&G); vertex_list = (struct Vertex*)malloc(sizeof(struct Vertex) * G.vertex_num); sum = Prim(&G, vertex_list, ); printf("%d\n", sum); Output(vertex_list, G.vertex_num); sum = Kruskal(&G); printf("%d\n", sum); }
Prim算法和Kruskal算法(图论中的最小生成树算法)的更多相关文章
- 转载:最小生成树-Prim算法和Kruskal算法
本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...
- 最小生成树之Prim算法和Kruskal算法
最小生成树算法 一个连通图可能有多棵生成树,而最小生成树是一副连通加权无向图中一颗权值最小的生成树,它可以根据Prim算法和Kruskal算法得出,这两个算法分别从点和边的角度来解决. Prim算法 ...
- java实现最小生成树的prim算法和kruskal算法
在边赋权图中,权值总和最小的生成树称为最小生成树.构造最小生成树有两种算法,分别是prim算法和kruskal算法.在边赋权图中,如下图所示: 在上述赋权图中,可以看到图的顶点编号和顶点之间邻接边的权 ...
- 最小生成树——Prim算法和Kruskal算法
洛谷P3366 最小生成树板子题 这篇博客介绍两个算法:Prim算法和Kruskal算法,两个算法各有优劣 一般来说当图比较稀疏的时候,Kruskal算法比较快 而当图很密集,Prim算法就大显身手了 ...
- 最小生成树Prim算法和Kruskal算法
Prim算法(使用visited数组实现) Prim算法求最小生成树的时候和边数无关,和顶点树有关,所以适合求解稠密网的最小生成树. Prim算法的步骤包括: 1. 将一个图分为两部分,一部分归为点集 ...
- Prim算法和Kruskal算法
Prim算法和Kruskal算法都能从连通图找出最小生成树.区别在于Prim算法是以某个顶点出发挨个找,而Kruskal是先排序边,每次选出最短距离的边再找. 一.Prim(普里姆算法)算法: ...
- 【数据结构】最小生成树之prim算法和kruskal算法
在日常生活中解决问题经常需要考虑最优的问题,而最小生成树就是其中的一种.看了很多博客,先总结如下,只需要您20分钟的时间,就能完全理解. 比如:有四个村庄要修四条路,让村子能两两联系起来,这时就有最优 ...
- Prim算法和Kruskal算法的正确性证明
今天学习了Prim算法和Kruskal算法,因为书中只给出了算法的实现,而没有给出关于算法正确性的证明,所以尝试着给出了自己的证明.刚才看了一下<算法>一书中的相关章节,使用了切分定理来证 ...
- 最小生成树---Prim算法和Kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
- prim 算法和 kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
随机推荐
- android 4.4.2 开发环境
1.设置环境变量 set "JAVA_HOME=C:\Program Files\Java\jdk1.7.0_75" set "ANT_HOME=D:\tools\and ...
- ubuntu12.04+proftpd1.3.4a的系统用户+虚拟用户权限应用实践
目录: 一.什么是Proftpd? 二.Proftpd的官方网站在哪里? 三.在哪里下载? 四.如何安装? 1)系统用户的配置+权限控制 2)虚拟用户的配置+权限控制 一.什么是Proftpd? ...
- selenium加载时间过长
为了获取网站js渲染后的html,需要利用selenium加载网站,但是会出现加载时间过长的现象,因此可以限制其加载时间以及强制关掉加载: # !/usr/bin/python3.4 # -*- co ...
- [内核同步]浅析Linux内核同步机制
转自:http://blog.csdn.net/fzubbsc/article/details/37736683?utm_source=tuicool&utm_medium=referral ...
- Codeforces Round #378 (Div. 2) D - Kostya the Sculptor
Kostya the Sculptor 这次cf打的又是心累啊,果然我太菜,真的该认真学习,不要随便的浪费时间啦 [题目链接]Kostya the Sculptor &题意: 给你n个长方体, ...
- python模块介绍- SocketServer 网络服务框架
来源:https://my.oschina.net/u/1433482/blog/190612 摘要: SocketServer简化了网络服务器的编写.它有4个类:TCPServer,UDPServe ...
- CRM 日期类型的一些处理JS
//当前日期 var now = new Date(); //换算为毫秒数 var now_ms = Date.UTC( now.getFullYear(), now.getMonth(),now.g ...
- shutdown immediate时 hang住 (转载)
shutdown immediate 经常关库时hang住,在alert中有 License high water mark = 4All dispatchers and shared servers ...
- Spark On Yarn中spark.yarn.jar属性的使用
今天在测试spark-sql运行在yarn上的过程中,无意间从日志中发现了一个问题: spark-sql --master yarn // :: INFO Client: Requesting a n ...
- openldap加密传输sssd
http://blog.father.gedow.net/2015/09/29/sssd-ldap-sudo/ yum -y install openldap-clients sssd authcon ...