克鲁斯卡尔(Kruskal)算法

# include <stdio.h> # define MAX_VERTEXES //最大顶点数
# define MAXEDGE //边集数组最大值
# define INFINITY //代表不可能的数(无穷大) typedef struct
{//图 结构体定义
int arc[MAX_VERTEXES][MAX_VERTEXES];//二位数组 矩阵
int numVertexes, numEdges;//当前图中的顶点数和边数 }MGraph; typedef struct
{//边集数组 结构体定义
int begin;
int end;
int weight; }Edge; void CreateMGraph (MGraph *G)
{//创建
int i, j;
//下面是已经输入好的
G->numVertexes = ;
G->numEdges = ; for (i=; i<G->numVertexes; i++)
for (j=; j<G->numVertexes; j++)
if (i == j)
G->arc[i][j] = ;
else
G->arc[i][j] = G->arc[j][i] = INFINITY; G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=; for (i=; i<G->numVertexes; i++)
for (j=i+; j<G->numVertexes; j++)//矩阵的上三角,然后对称矩阵的下三角
G->arc[j][i] = G->arc[i][j];//对称
} 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; return ;
} void sort (Edge edges[], MGraph *G)
{//对权值进行排序
int i, j;
for (i=; i<G->numEdges; i++)
for (j=i+; j<G->numEdges; j++)//对存入有效边(两端点的权值)进行冒泡排序
if (edges[i].weight > edges[j].weight)
swapn (edges, i, j);//交换权值 printf ("排序过后:\n");
for (i=; i<G->numEdges; i++)
printf ("边:(%d,%d) 权值:%d\n", edges[i].begin, edges[i].end, edges[i].weight); return ;
} int Find (int *parent, int f)//★
{// 查找连线顶点的尾部下标
//走过的路都有记录,如果走已经走过的路的话,那么返回的值(n=m);
while (parent[f] > )
f = parent[f];
return f;
} void MiniSpanTree_Kruskal (MGraph G)
{//克鲁斯卡尔算法
int i, j, n, m;
int k = ;
int parent[MAX_VERTEXES];//定义一维数组判断是否形成环路
Edge edges[MAXEDGE];//定义边集数组 for (i=; i<G.numVertexes; i++)//存储有效的边(两个端点和权值)
for (j=i+; j<G.numVertexes; j++)//矩阵上三角进行比较,因为对称,所以比较一半更节约时间
if (G.arc[i][j] < INFINITY)
{
edges[k].begin = i;
edges[k].end = j;
edges[k ++].weight = G.arc[i][j];
}
sort(edges, &G);//排序 for (i=; i<G.numVertexes; i++)
parent[i] = ; printf ("\n打印最小生成树:\n");
for (i=; i<G.numEdges; 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);
}
}
} int main (void) {
MGraph G;
CreateMGraph (&G);//创建
MiniSpanTree_Kruskal (G);//克鲁斯卡尔 算法 return ;
} /*
在vc++6.0运行结果: 排序过后:
边:(4,7) 权值:7
边:(2,8) 权值:8
边:(0,1) 权值:10
边:(0,5) 权值:11
边:(1,8) 权值:12
边:(3,7) 权值:16
边:(1,6) 权值:16
边:(5,6) 权值:17
边:(1,2) 权值:18
边:(6,7) 权值:19
边:(3,4) 权值:20
边:(3,8) 权值:21
边:(2,3) 权值:22
边:(3,6) 权值:24
边:(4,5) 权值:26 打印最小生成树:
边(4,7) 权值:7
边(2,8) 权值:8
边(0,1) 权值:10
边(0,5) 权值:11
边(1,8) 权值:12
边(3,7) 权值:16
边(1,6) 权值:16
边(6,7) 权值:19
Press any key to continue
*/
克鲁斯卡尔(Kruskal)算法的更多相关文章
- 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用
图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...
- 洛谷P3366【模板】最小生成树-克鲁斯卡尔Kruskal算法详解附赠习题
链接 题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz 输入输出格式 输入格式: 第一行包含两个整数N.M,表示该图共有N个结点和M条无向边.(N<=5000,M&l ...
- 图解最小生成树 - 克鲁斯卡尔(Kruskal)算法
我们在前面讲过的<克里姆算法>是以某个顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树的.同样的思路,我们也可以直接就以边为目标去构建,因为权值为边上,直接找最小权值的边来构建生成树 ...
- 克鲁斯卡尔(Kruskal)算法求最小生成树
/* *Kruskal算法求MST */ #include <iostream> #include <cstdio> #include <cstring> #inc ...
- 最小生成树——Kruskal(克鲁斯卡尔)算法
[0]README 0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解 Kruskal(克鲁斯卡尔)算法 的idea 并用 源代码加以实现: 0.2)最小生成树的基础知识,参见 ...
- 经典问题----最小生成树(kruskal克鲁斯卡尔贪心算法)
题目简述:假如有一个无向连通图,有n个顶点,有许多(带有权值即长度)边,让你用在其中选n-1条边把这n个顶点连起来,不漏掉任何一个点,然后这n-1条边的权值总和最小,就是最小生成树了,注意,不可绕成圈 ...
- 最小生成树之克鲁斯卡尔(kruskal)算法
#include <iostream> #include <string> using namespace std; typedef struct MGraph{ string ...
- 数据结构与算法——克鲁斯卡尔(Kruskal)算法
目录 应用场景-公交站问题 克鲁斯卡尔算法介绍 克鲁斯卡尔算法图解 克鲁斯卡尔算法分析 如何判断回路? 代码实现 无向图构建 克鲁斯卡尔算法实现 获取一个点的终点解释 应用场景-公交站问题 某城市新增 ...
- 图->连通性->最小生成树(克鲁斯卡尔算法)
文字描述 上一篇博客介绍了最小生成树(普里姆算法),知道了普里姆算法求最小生成树的时间复杂度为n^2, 就是说复杂度与顶点数无关,而与弧的数量没有关系: 而用克鲁斯卡尔(Kruskal)算法求最小生成 ...
随机推荐
- 会场安排问题--nyoj题目14
会场安排问题 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 学校的小礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办.小刘的工 ...
- java学习:AWT组件和事件处理的笔记(1)--菜单条,菜单,菜单项
菜单放在菜单条里,菜单项放在菜单里1.MenuBar 在java.awt包中,负责创建菜单条,即MenuBar的一个实例,便是一个菜单条. 在Frame类中的setMenuBar(Menu ...
- 进程外Session和进程内Session存储
- SARscape5.2哨兵1A数据的读取
SARscape5.2支持哨兵1A数据的读取,支持的数据类型有: SM SLC ——条带模式的斜距单视复数产品 IW SLC——干涉宽幅模式(TOPS Mode)的斜距单视复数产品 EW SLC——超 ...
- SQL Server 2008数据库的一些基本概念 区、页、行
原文地址:http://www.cnblogs.com/liuzhendong/archive/2011/10/11/2207361.html 以前总是没弄明白这些基本概念,现在整理如下: 1.区: ...
- linux之SQL语句简明教程---Subquery
我们可以在一个 SQL 语句中放入另一个 SQL 语句.当我们在 WHERE 子句或 HAVING 子句中插入另一个 SQL 语句时,我们就有一个 subquery 的架构. Subquery 的作用 ...
- hdu1258Sum It Up (DFS)
Description Given a specified total t and a list of n integers, find all distinct sums using numbers ...
- 杭电oj1219 AC Me
Tips:本题中,输入字符串之后,直接从头到尾处理一遍,调用函数判断是否是字母,不要自己写循环判断是否为字母,易超时! 不过本题中有一个疑问,自己最开始用C写的,一直是Time Limit Excee ...
- Frameset标签
Frameset标签不能在body中设置. <!DOCTYPE html> <html> <head> <title>框架标签</title> ...
- rand,randn,randi函数区别
1,rand 生成均匀分布的伪随机数.分布在(0~1)之间 主要语法:rand(m,n)生成m行n列的均匀分布的伪随机数 rand(m,n,'double')生成指定精度的 ...