数据结构与算法——图的最小生成树之克鲁斯卡尔算法
图的最小生成树之克鲁斯卡尔算法
克鲁斯卡尔算法是以某个顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树。
克鲁斯卡尔算法需要将边集数组按照权值从小到大排序,如下所示:
看图分析:
1. 克鲁斯卡尔算法它的基本思想有别于普利姆算法,它是按顺序利用具有最优权值边去构建最小生成树,这个过程的关键是在逐一利用最优边时,保证生成的是一个树,而不是闭环的图,如果要使生成树的过程中不会闭环,我们要保证,从已选择边的任何一个点起,都不会形成一个闭环;
2. 结合图来看:选择前6个边之后的图示如下,从任何一个点起都不会回到自己,那么接着看边集数组的第7个元素:顶点V5-->V6的边,如果加入V5-->V6的边,就会形成一个闭环,所以不能使用这个边,跳到边集数组的下一个元素;
3. 来看这个闭环如何判断:如果我们能记录当前已选择边的顶点的尾顶点,并依次去查找尾顶点,如果不能回到该顶点,那么肯定就不会形成闭环,是不是像极了链表的闭环判断。
实现伪代码:
typedef struct
{
int begin;
int end;
int weight;
}Edge;#define MAXEDGE 15
int Find(int *parent, int f)
{
//遍历该顶点串起的所有边,返回最后的尾顶点索引
while (parent[f] > 0)
{
f = parent[f];
}return f;
}void MiniSpanTree_Kruskai(MGraph G)
{
int i, m, n;
Edge edges[MAXEDGE];
int parent[MAXEDGE];//记录顶点索引生成边的尾顶点for (i = 0; i < G.numVertexes; i++)
{
parent[i] = 0;//初始为0,当前没有任何边
}for (i = 0; i < G.numVertexes; i++)
{
//闭环的判断,对照上述3的描述
n = Find(parent, edges[i].begin);
m = Find(parent, edges[i].end);if (n != m)
{
parent[n] = m;//更新该顶点已找到的尾点
cout << "( " << edges[i].begin << ".," << edges[i].end << " ) " << endl;
}}
}
以上参考:
- 大话数据结构