采用克鲁斯卡尔算法求最小生成树

目的:领会克鲁斯卡尔算法求带权连通图中最小生成树的过程和相关算法设计。

内容:编写一个程序exp8-7.cpp,实现求带权连通图最小生成树的克鲁斯卡尔算法。对于如图8.55所示的带权连通图G,输出从顶点0出发的一颗最小生成树。

[  数据结构教程(第5版)李春葆 主编   ]  第8章上机练习实验题6

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
struct MatGraph
{
    int edges[100][100];
    int n;
};
typedef struct
{
    int u,v;
    int w;
}Edge;
bool cmp (Edge a,Edge b)
{
    return a.w<b.w;
}
void Kruskal(MatGraph g)//Kruskal算法
{
    int i,j,k,u1,v1,sn1,sn2;
    int vset[1000];
    Edge E[1000];//存放图中的所有边
    k=0;//e数组的下标从0开始计
    for(i=0;i<g.n;i++)//由g产生边集E,不重复选取同一条边
        for(j=0;j<=i;j++)
        {
            if(g.edges[i][j]!=0&&g.edges[i][j]!=INF)
            {
                E[k].u=i;E[k].v=j;
                E[k].w=g.edges[i][j];
                k++;
            }
        }
    sort(E,E+k,cmp);
    for(i=0;i<g.n;i++)//初始化辅助数组
        vset[i]=i;
    k=1;//k表示当前构造生成树的第几条边,初值为1
    j=0;//E中边的下标,初值为0
    while(k<g.n)//生成的边数小于n时循环
    {
        u1=E[j].u;v1=E[j].v;//取一条边的两个顶点
        sn1=vset[u1];
        sn2=vset[v1];//分别得到两个边所属的集合编号
        if(sn1!=sn2)//两顶点属于不同的集合,该边是最小生成树的一条边
        {
            printf("边(%d,%d)权为:%d\n",u1,v1,E[j].w);//输出最小生成树的一条边
            k++;//生成边数增1
            for(i=0;i<g.n;i++)//两个集合统一编号
                if(vset[i]==sn2)//集合编号为sn2的改为sn1
                    vset[i]=sn1;
        }
        j++;//扫描下一条边
    }
}
int main()
{
    int i,j;
    MatGraph g;
    g.n=6;
    for(i=0;i<=5;i++)
        for(j=0;j<=5;j++){
            if(i==j) g.edges[i][j]=0;
            else g.edges[i][j]=INF;
        }
    g.edges[0][1]=g.edges[1][0]=5;
    g.edges[0][2]=g.edges[2][0]=8;
    g.edges[0][3]=g.edges[3][0]=7;
    g.edges[0][5]=g.edges[5][0]=3;
    g.edges[1][2]=g.edges[2][1]=4;
    g.edges[2][3]=g.edges[3][2]=5;
    g.edges[2][5]=g.edges[5][2]=9;
    g.edges[3][4]=g.edges[4][3]=5;
    g.edges[3][5]=g.edges[5][3]=6;
    g.edges[4][5]=g.edges[5][4]=1;
    printf("克鲁斯卡尔算法所求的最小生成树为:\n");
    Kruskal(g);
    return 0;
}

运行结果如下:

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Python实现克鲁斯卡尔算法最小生成树的代码,供参考: ```python class Kruskal: def __init__(self, num_vertices): self.num_vertices = num_vertices self.parent = [i for i in range(num_vertices)] def find(self, vertex): if self.parent[vertex] != vertex: self.parent[vertex] = self.find(self.parent[vertex]) return self.parent[vertex] def union(self, vertex1, vertex2): parent1 = self.find(vertex1) parent2 = self.find(vertex2) self.parent[parent1] = parent2 def kruskal(self, edges): mst = [] edges = sorted(edges, key=lambda x: x[2]) for edge in edges: vertex1, vertex2, weight = edge if self.find(vertex1) != self.find(vertex2): self.union(vertex1, vertex2) mst.append(edge) return mst ``` 在上面的代码中,我们定义了一个`Kruskal`类,其中包含了`find`和`union`两个函数来实现并查集,以及`kruskal`函数来实现克鲁斯卡尔算法。具体来说: - `find`函数:用于查找给定顶点的祖先节点,如果该顶点不是根节点,则递归查找其祖先节点并进行路径压缩优化,最终返回该顶点的根节点。 - `union`函数:用于合并两个顶点所在的连通块,将其中一个的祖先节点指向另一个的祖先节点。 - `kruskal`函数:实现克鲁斯卡尔算法,首先按照边权值从小到大排序,然后依次遍历每一条边,如果该边连接的两个顶点不在同一个连通块中,则将它们合并,并将该边加入最小生成树中。 使用该类的示例如下: ```python # 创建Kruskal对象,传入顶点数目 k = Kruskal(5) # 边列表,每个元素为一个三元组,分别表示边的两个顶点和权值 edges = [(0, 1, 2), (0, 3, 6), (1, 2, 3), (1, 3, 8), (1, 4, 5), (2, 4, 7), (3, 4, 9)] # 调用kruskal函数最小生成树 mst = k.kruskal(edges) # 输出最小生成树 for edge in mst: print("顶点{}和顶点{}之间的边,权值为{}".format(edge[0], edge[1], edge[2])) ``` 输出结果为: ``` 顶点0和顶点1之间的边,权值为2 顶点1和顶点2之间的边,权值为3 顶点1和顶点4之间的边,权值为5 顶点0和顶点3之间的边,权值为6 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值