克鲁斯卡尔算法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了克鲁斯卡尔算法相关的知识,希望对你有一定的参考价值。

你好!这是代码
/* Kruskal算法生成最小生成树 */

void MiniSpanTree_Kruskal (MGraph G) /* 生成最小生成树 */

int i, n, m;

Edge edges[MAXEDGE]; /* 定义边集数组 */

int parent[MAXVEX]; /* 定义一数组用来判断边与边是否形成环路 */

/* 此处省略将邻接矩阵G转化为边集数组edges,并按权由小到大排列的代码 */

for (i=0; i<G.numVertexes; i++)
parent[i] = 0; /* 初始化数组为0 */

for(i=0; i<G.numEdges; i++) /* 循环每一条边 */

n = Find(parent, edges[i].begin);

m = Find(parent, edges[i].end);

if (n != m) /* 假如n与m不等,说明此边没有与现有生成树形成环路 */

parent[n] = m; /* 将此边的结尾顶点放入下标为起点的parent中,表示此顶点已经在生成树集合中 */

printf("(%d,%d) %d ",edges[i].begin,edges[i].end,edges[i].weight);





int Find(int* parent, int f) /* 查找连线顶点的尾部下标 */

while(parent[f] > 0)
f = parent[f];

return f;


请问这个parent数组的作用是什么,为什么要赋初值0;
还有就是:
f (n != m) /* 假如n与m不等,说明此边没有与现有生成树形成环路 */

parent[n] = m; /* 将此边的结尾顶点放入下标为起点的parent中,表示此顶点已经在生成树集合中 */

int Find(int* parent, int f) /* 查找连线顶点的尾部下标 */

while(parent[f] > 0)
f = parent[f];

return f;


这两部分实在是不懂,求大神指教!

其实这个parent 数组就是用来判断新选择的边是否和现有的边构成环路
这个结构就是一个树的双亲表示,当新边的两个顶点所在的树根不是同一个时,自然就是表示加入这两个顶点间的边不够成环路
这种结构通称“并查集”,用来检测等价关系的,这里用来判断顶点是否在一个集合中,可以看比较全面的《数据结构》教材树那个一章的介绍追问

树的章节会讲并查集吗?能否详细讲解下int Find(int* parent, int f) 的构思

追答

并查集的存储结构本来就是一个树的双亲表示,一般比较全的教材都在树那一章里面
你的程序中根的双亲用0表示,find函数中的那个循环就是找到这个树根的编号(下标)

参考技术A 哈哈,因为爱情。
parent数组装的是每个连通分量的第一个开始点,最初的状态有n个节点,n个分量,都是第一个,所以全都赋值0,而开始合并后,将一个个的分量逐步的合并到一起,parent记录的就是父节点,一个联通分量只有一个parent为0的。
而判断循环是如果两个的最终的开始节点是同一个,就说明你加上这条边就形成循环了,这条边就不能加

以上是关于克鲁斯卡尔算法的主要内容,如果未能解决你的问题,请参考以下文章

最小生成树 普里姆算法和克鲁斯卡尔算法

克鲁斯卡尔算法

克鲁斯卡尔算法是怎样判断是不是构成了回路

什么是克鲁斯卡尔算法

克鲁斯卡尔算法

克鲁斯卡尔算法 判断回路中的问题