4 Kruskal算法的设计---来源王英S同学

这篇博客介绍了如何在C++中实现Kruskal算法,用于生成无向网的最小生成树。首先,详细解释了Kruskal算法的基本思想和步骤,包括边的权值排序、判断回路的方法。接着,展示了代码实现,包括邻接表ADT的数据结构和Kruskal算法的成员函数。最后,给出了输入输出样例,演示了算法的运行过程和结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来源王英S同学

来源王英S同学

来源王英S同学

作者: 冯向阳时间限制: 1S章节: 课程设计

问题描述 :

在使用vector(数组)、图的邻接表ADT以及快速排序的基础上,设计Kruskal算法,用以生成无向网的最小生成树,并以文本形式输出生成树中各条边以及它们的权值。将此算法加入到邻接表ADT中,在邻接表ADT中提供一个公有的成员函数Kyuskal。

提示:

(1)Kruskal算法的基本思想是为使生成树上边的权值之和达到最小,则应使生成树中每一条边的权值尽可能地小。初始时,先构造一个只含n个顶点的子图 T,然后从权值最小的边开始,若它的添加不使T中产生回路,则在T上加上这条边,如此重复,直至加上n-1条边为止。具体来讲,Kruskal算法由以下几个步骤组成:

1)设母图G=(V,E)为一个具有n个顶点的带权的连通网络,其最小生成树的初始状态为有n个顶点但无边的非连通图 T=(V, Φ)。

2)将E中的边按权值的递增顺序排序。

3)选择权值最小的边,若不构成环,则将其加入T中,否则,将其弃舍。

4)循环至有N-1条边。

(1)在排序的过程中,由于根据边的权值大小进行排序,需要同步保持边的权值和边之间的对应关系。

(2)定义vector<pair<TypeOfEdge, int>>,pair->first对应边的权值,pair->second对应边,使用sort进行排序。

(3)实现Kruskal算法的关键是如何判断所选取的边是否与生成树中已保留的边形成回路,这可通过判断边的两个顶点所在的连通分量的方法来解决。为此设置一个辅助数组vest(数组元素下标为0~n-1),它用于判断两个顶点集合(即两个连通分量),此时按其中的一个集合编号重新统一编号(即合并成一个连通分量)。因此,当两个顶点的集合(连通分量)编号不同时,则加入这两个顶点所构成的边到最小生成树中就一定不会形成回路,因为这两个顶点分属于不同的连通分量。

(4)由于我们需要的是最小生成树,所以母图是不用实际生成的,仅仅需要它的原始数据。

注意:处理的图的类型均为无向网(UDN),权值类型为int或double

参考函数原型:

//Kruskal算法
template<class TypeOfVer, class TypeOfEdge>
bool adjlist_graph<TypeOfVer, TypeOfEdge>::Kruskal( int esize,  int **edge, TypeOfEdge *weight,  TypeOfEdge &cost);

                       //esize:边的数量   **edge:输入的边集二维数组  *weight:初始的权值数组  cost 树的代价 

输入说明 :

第一行:权值数据类型(0:int;1:double)//暂不考虑容错处理

第二行:图的类型

第三行:顶点数

第四行:顶点集

第五行:边数

第六行:边集

第七行:权集

输出说明 :

第一行:图的类型

第二行:顶点集

     空行

第三行:排序前的边的权值结果(按照输入顺序)

第四行:排序前对应的边的序号关系(按照输入顺序)

     空行

第三行:排序后的边的权值结果(按照权值递增排序顺序)

第四行:排序后的对应的边的序号关系(对应权值递增排序顺序)

     空行

第五行:最小生成树的各条边以及它们的权值(格式如测试数据所示)

   空行

第六行:最小生成树的代价

输入范例 :

0
UDN
6
1 2 3 4 5 6
10
0 1
0 2
0 3
1 2
1 4
2 3
2 4
2 5
3 5
4 5
6 1 5 5 3 5 6 4 2 6

输出范例 :

UDN
6 1 5 5 3 5 6 4 2 6 
0 1 2 3 4 5 6 7 8 9 

1 2 3 4 5 5 5 6 6 6 
1 8 4 7 2 3 5 0 6 9 

(1,3),1
(4,6),2
(2,5),3
(3,6),4
(2,3),5

15

#include<iostream>
#include<algorithm>
using namespace std;
struct edge
{
    int x,y;
    double quan;
    int name;
} a[10010];
bool cmp(edge x,edge y)
{
    return x.quan<y.quan;
}
double sum=0;
void Kruskal(edge a[10010],int n,char node[10010])
{
    int vest[1010];
    int j,u1,v1,sn1,sn2,k=1,i=0;
    for(int q=0; q<n; q++)
        vest[q]=q;
    while(k<n)
    {
        u1=a[i].x;
        v1=a[i].y;
        sn1=vest[u1];
        sn2=vest[v1];
        if(sn1!=sn2)
        {
            cout<<"("<<node[u1]<<","<<node[v1]<<")"<<","<<a[i].quan<<endl;
            k++;
            for(int p=0; p<n; p++)
            {
                if(vest[p]==sn2)
                    vest[p]=sn1;
            }
            sum+=a[i].quan;
        }
        i++;
    }
    cout<<endl;
    cout<<sum;
}
int main()
{
    int flag,n,m;
    string b;
    cin>>flag;
    cin>>b;
    cin>>n;
    char node[10010];
    for(int i=0; i<n; i++)
        cin>>node[i];
    cin>>m;
    for(int i=0; i<m; i++)
        cin>>a[i].x>>a[i].y,a[i].name=i;
    for(int i=0; i<m; i++)
        cin>>a[i].quan;
    cout<<b<<endl;
    for(int i=0; i<m; i++)
        cout<<a[i].quan<<" ";
    cout<<endl;
    for(int i=0; i<m; i++)
        cout<<a[i].name<<" ";
    cout<<endl<<endl;
    sort(a,a+m,cmp);
    for(int i=0; i<m; i++)
        cout<<a[i].quan<<" ";
    cout<<endl;
    for(int i=0; i<m; i++)
        cout<<a[i].name<<" ";
    cout<<endl<<endl;
    Kruskal(a,n,node);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值