最小生成树 Kruskal 算法 和 Prim算法
来源:互联网 发布:node留言板 编辑:程序博客网 时间:2024/06/05 11:12
Kruskal 算法 和 Prim算法 是 最小生成树基础的两种算法:
本文章中的代码用c语言写的(不过头文件用了c++ 的,大家不要在意), 其实在 Kruskal 算法 里面对数据进行排序的时候 可以用 C++ 库函数 的 sort排序进行排序 ,不过这里面我写了一个 快排,用快排进行排序了! 在 Kruskal 算法 里面,用到了并查集的 查询 和 合并 两个函数,主要是用来检查某个节点是否用过!
Prim算法 如果你仔细研究的话你会发现,Prim算法 和 最短路 的 Dijkstra 的算法的思想比较相似,基本可以说Prim 运用了 最短路 Dijkstra 的思想!
先给出一组测试数据:
输入第一行有两个数 n 和 m,n 表示有n个城市,m表示有m条道路。接下来的m行,每行形容“a b c”用来表示一条路,意思是城市a 到城市 b 的路径长度为 c。
输入:6 92 4 113 5 134 6 35 6 42 3 64 5 71 2 13 4 91 3 2输出结果:19
// Kruskal 算法: 这里的 Kruskal 算法 的时间复杂度是 O(nlog(n))#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>using namespace std;struct edge{int u;int v;int w;};struct edge e[110];int n,m;int f[7] = {0},sum = 0,Count = 0;void quicksort(int left,int right) // 快速排序 {int i,j;struct edge t;if(left > right)return;i = left;j = right;while(i != j){while(e[j].w >= e[left].w && i < j)j--;while(e[i].w <= e[left].w && i < j)i++;if(i < j){t = e[i];e[i] = e[j];e[j] = t;}}t = e[left];e[left] = e[i];e[i] = t;quicksort(left,i - 1);quicksort(i + 1,right);return;}int getf(int v) // 并查集查找根节点 {if(f[v] == v)return v;else{f[v] = getf(f[v]);return f[v];}}int merge(int v,int u) // 将两棵树合并 {int t1,t2;t1 = getf(v);t2 = getf(u);if(t1 != t2){f[t2] = t1;return 1;}return 0;}int main(){int i;scanf("%d%d",&n,&m);for(i = 1;i <= m;i++){scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);}quicksort(1,m); // 按照权值从小到大对边进行快速排序for(i = 1;i <= n;i++) // 并查集根节点的初始化 {f[i] = i;} for(i = 1;i <= m;i++) // 权值已经按照从小到大排序好了,所以可以直接将不在同一颗树的两颗树合并成一颗树 {if(merge(e[i].u,e[i].v)){Count++;sum += e[i].w;}if(Count == n - 1) // 直到合并到 n - 1 次 ,也是就将 n 棵树树合并成一棵树,跳出循环,这个树就是最小生成树 break;}printf("%d\n",sum);return 0;}
// Prim算法 该代码 的时间复杂度 为 O(n^2) 如果借助“堆”,然后使用邻接表来储存图的话时间可达到 O(nlog(n))#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio> using namespace std;int main(){int n,m,i,j,k,min,t1,t2,t3;int e[7][7],dis[7],book[7] = {0};int inf = 99999999;int count = 0,sum = 0;scanf("%d%d",&n,&m);for(i = 0;i <= n;i++) // 进行一个初始化 {for(j = 1;j <= n;j++){if(i == j) // 自己到自己 权为 0 e[i][j] = 0;elsee[i][j] = inf; // 自己到其他 权为 inf }}for(i = 1;i <= m;i++) // 根据题里给的条件 更新相应的权值 {scanf("%d%d%d",&t1,&t2,&t3);e[t1][t2] = t3;e[t2][t1] = t3;}// 初始化dis数组,这里是1号顶点到各个顶点的初始距离,因为当前生成树中只有1号顶点 for(i = 1;i <= n;i++){dis[i] = e[1][i];}book[1] = 1; // book 标记该顶点是否已经加入生成树count++;while(count < n){min = inf;for(i = 1;i <= n;i++) // 寻找生成树到 i 节点的最小长度的路径 {if(book[i] == 0 && dis[i] < min){min = dis[i];j = i;}}book[j] = 1; // 找到后将 i 节点接到 生成树上 count++;sum += dis[j]; // 总路径长度加上新增加的长度,更新总长度 // 扫描当前顶点 j 所有的边,再以j为中间点,更新生成树到每一个非树顶点的距离 for(k = 1;k <= n;k++){if(book[k] == 0 && dis[k] > e[j][k])dis[k] = e[j][k];}} printf("%d\n",sum);return 0;}
0 0
- 最小生成树--Prim和Kruskal算法
- 最小生成树 prim算法和kruskal
- 最小生成树Prim和Kruskal算法
- 最小生成树算法:prim和kruskal
- 最小生成树 ,prim 和Kruskal 算法
- 最小生成树prim和kruskal算法
- Kruskal和Prim--最小生成树算法
- 最小生成树算法 :Prim算法 和 Kruskal 算法
- 最小生成树算法—Kruskal算法和Prim算法
- 最小生成树-Kruskal算法-Prim算法
- 最小生成树 Prim算法 Kruskal算法
- 最小生成树Prim算法Kruskal算法
- 最小生成树Prim算法,Kruskal算法
- 最小生成树(Prim算法和Kruskal算法)
- [最小生成树]Prim算法和Kruskal算法
- 最小生成树(Prim算法和Kruskal算法)
- 最小生成树—kruskal算法和prim算法
- 最小生成树:Prim算法和Kruskal算法
- python解决SNIMissingWarning和InsecurePlatformWarning警告
- eclipse 上使用recycleview,cardview的办法
- Systrace快捷命令
- Linux 网络设备驱动开发(一) —— linux内核网络分层结构
- tabindex的用法
- 最小生成树 Kruskal 算法 和 Prim算法
- HDU 4971 最大权闭合图
- hdu2571 命运
- 学生接外包需注意的地方
- Rescue The Princess
- python循环语句
- 操作系统2015(四川大学软件学院)
- 横向listview
- 设计模式之建造者模式(Builder)