最小生成树的构造

prim算法(破圈法)

kruskal算法(避圈法)

基本思想:

设G=(V,E)是网络,最小生成树的初始状态为只有VN个顶点而无边的非联通图T,T中每个顶点自成一个连通图。将集合E中的边按权递增顺序排列,选择 两个顶点分别在不通风的连通图且权最小的 边加入图T,则原来的两个连通图成为一个连通图。以此类推,知道T中所有的顶点都在同一个连通图中为止,该连通图就是所求的最小生成树。处理过程中加入边时避免产生回路,所以该算法也称避圈法。

储存结构:

1.图采用邻接矩阵表示。

2.mst数组类型为Edge,包括边的起点、终点和权。算法结束后,mst存放求出的最小生成树的VN-1条边。

3.用一个整型数组status[0...VN-1]记录各个顶点所属的连通子图,每个连通子图用一个顶点的下表表示。

代码实现:

#include <iostream>
#define AdjType int
#define VN 6
#define MAX 1000
using namespace std;

struct GraphMatrix
{
    AdjType arc[VN][VN];
};
typedef struct{
    int start,stop;
    AdjType weight;
}Edge;
Edge mst[VN-1];

void kruskal(GraphMatrix* Pgraph,Edge *mst)
{
    int num=0,x,y,minWeight,status[VN];
    for(int i=0;i<VN;i++)
        status[i]=i;//每个顶点属于自己代表的连通子图
    while(num<VN-1){
        minWeight=MAX;
        for(int i=0;i<VN-1;i++)//找到最短边
        for(int j=i+1;j<VN;j++){
            if(Pgraph->arc[i][j]<minWeight){
                x=i;y=j;minWeight=Pgraph->arc[i][j];
            }
        }
        if(minWeight==MAX){
            cout<<"No MST!\n";
            return ;
        }
        if(status[x]!=status[y]){//不属于同一连通子图
            mst[num].start=x;
            mst[num].stop=y;
            mst[num].weight=minWeight;
            num++;

            int j=status[y]; //原来statu[y]代表的连通子图的结点,现都属于status[x]代表的连通子图
            for(int i=0;i<VN;i++)
            if(status[i]==j)
                status[i]=status[x];
        }
        Pgraph->arc[y][x]=Pgraph->arc[x][y]=MAX;//删除已加入T的最短边
    }
    cout<<"Edges(start_ver,stop_vex,weight) of MST:\n";
    for(int i=0;i<VN-1;i++)
        cout<<"("<<mst[i].start<<","<<mst[i].stop<<","<<mst[i].weight<<")\n";
}
int main()
{
    GraphMatrix *G=new struct GraphMatrix;
    for(int i=0;i<VN;i++)
        for(int j=0;j<VN;j++)
            cin>>G->arc[i][j];
    kruskal(G,mst);
    return 0;
}
时间复杂度为O(n^3)。

Input

0 10 1000 1000 19 21
10 0 5 6 1000 11
1000 5 0 6 1000 1000
1000 6 6 0 18 14
19 1000 1000 18 0 33
21 11 1000 14 33 0

Output

Edges(start_ver,stop_vex,weight) of MST:
(1,2,5)
(1,3,6)
(0,1,10)
(1,5,11)
(3,4,18)



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值