克鲁斯卡尔最小生成树算法的C语言实现

4

我正在学习Kruskal算法,该算法用于查找给定图的最小生成树(MST),基本概念是将所有顶点初始视为森林。然后,找到最小边并将边的顶点合并成一棵树。一直递归执行此过程,直到只剩下包含所有顶点的一棵树。

我看到了以下实现:

#include<iostream.h>

int p[10];

void kruskal(int w[10][10],int n)
{
    int min,sum=0,ne=0,i,j,u,v,a,b;
    for(i=1;i<=n;i++)
    p[i]=0;
    while(ne<n-1)
    {
        min=999;
        for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        {
            if(w[i][j]<min)
            {
                    min=w[i][j];
                u=a=i;
                v=b=j;
            }
        }
        while(p[u])
            u=p[u];
        while(p[v])
            v=p[v];
        if(u!=v)
        {
            ne++;
            sum+=min;
            cout<<"\nedge "<<a<<"-->"<<b<<" is "<<min;
            p[v]=u;
        }
        w[a][b]=w[b][a]=999;
    }
    cout<<"\nmin cost spanning tree= "<<sum;
}

void main()
{
    int w[10][10],n,i,j;
    clrscr();
    cout<<"enter no.of vertices\n";
    cin>>n;
    cout<<"enter weight matrix\n";
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            cin>>w[i][j];
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(w[i][j]==0)
                w[i][j]=999;
    kruskal(w,n);
}

我不理解的是需要什么:

我不明白的是需要什么:

while(p[u])
    u=p[u];
while(p[v])
    v=p[v];

这两个 while 循环究竟是做什么的?

编辑:还有它们的必要性-

for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(w[i][j]==0)
                w[i][j]=999; 
1个回答

9
Kruskal算法想要添加边,但在此之前,它必须检查是否已连接(如果已连接,则不会添加该边)。
给出的四行代码正是检查
是否已连接。
要完全理解此操作,您需要知道以下内容:最初,和分别设置为
。数组

存储连接的组件,即表示:在的连接组件中。请注意,最初每个顶点代表自己的连接组件,由表示(即,将组件设置为0)。

此外,请注意,每个连接组件由一个顶点表示。
因此,我们继续:while(p[u])检查是否是组件的代表(如果是代表,则导致while循环停止)。因此,如果是组件的代表,它就会停止。
更有趣的部分是下面的内容:如果不是一个代表,该算法将查找,即查找哪个节点是的组件的代表。然后,相应地更新=p[u]>)。
您可以将整个游戏视为图形。考虑以下表示连接组件的表:
   u  |  1  2  3  4  5  6  7  8  9
 p[u] |  2  0  2  3  2  1  0  9  0

这意味着节点1属于由2表示的组件。4属于由3表示的组件,而3本身属于由2表示的组件。请注意,2是代表,因为它有条目0
您可以将此可视化为图形:
  2      7  9
 /|\        |
1 3 5       8
| |
6 4

你看,我们当前有三个组件,分别由2、7和9表示。
现在如果我们想要添加一个新边(6,7),我们需要"向上遍历树",直到找到代表2和7的节点。如我们所见,这些节点不相同,因此我们添加了这条边。
再来看另一个例子:我们想要添加边(6,5),那么我们就"向上遍历树"并在两种情况下找到了代表2。因此,我们不添加该边。
"向上遍历树"是通过你明确指定的行来完成的。

这里的“组件”是什么意思?是已经作为MST的一部分添加的顶点吗? - Chaitanya Nettem
1
@guy,Kruskal算法有中间步骤,其中两个连通分量被合并。如果添加一条新边,则必须在两个连通分量之间添加。这些组件存储在“p”中。 - phimuemue
那个例子帮了很大的忙! :) - Chaitanya Nettem
所以 if(u!=v) 语句检查代表是否不同,以确保没有循环。我是对的吗? - Chaitanya Nettem
1
@Huzo 不确定,但如果我没记错的话,它适用于无向图。(也许这可以帮助你:https://dev59.com/4WEh5IYBdhLWcg3wPRSq?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa) - phimuemue
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接