数据结构 之 Prim算法的应用 之 MST(最小生成树)

算法:Prim

应用:对一个带权无向图生成 (权值)最小生成树

 

(程序来自《天勤 数据结构 高分笔记》)

 

今日一签,赠给奋斗的自己和你们:

人生不能像做菜,把所有的材料都准备好了才下锅。
——李安《饮食男女》

 

讲述算法前,先做如下的说明:

1. 带权无向图的存储

把一个共有N个结点的带权无向图的信息(边以及边的权值)存放在一个大小为NN的二维方阵中。

带权无向图的N个结点的编号是0N-1

方阵元素[i][j]表示节点编号是ij2个节点之间的边的权值,

行标 = 列标 的 方阵元素 规定 其值是0,表示结点自身到自身的权值是0

宏定义一个常量INF,把它的值设为大于图中所有边权值的一个数,这个自定,

若图中结点i与结点j之间没有边,规定二维方阵中的元素[i][j]的值是INF,表示两个结点之间的权值是无穷大。

图由结点和边构成,所以,结构体定义如下:

#define MAXSIZE 100

#define INF     500

 

typedef struct

{

    int no;         // 存放结点的编号

    char info;     // 存放结点的信息

}VertexType;         // 结点

 

typedef struct

{

    int n,e;                     // n: 存放图的结点总数,e: 存放图的边的总数

    int edges[MAXSIZE][MAXSIZE]; // 存放带权无向图的边和边的权值信息

    VertexType vex[MAXSIZE];     // 存放带权无向图的结点信息

}MGraph; //

 

2.

树只有一个根,根下是各个子树,并且很重要的一点是这些子树互不相交,

所以树中是没有环的,

所以,在做这个算法的时候,不能到最后生成的是一个带环的图,

避免出现环,需要一个判断语句,这个判断语句什么时候应该出现,它的内容是什么,

读程序的时候请格外注意。

 

3. C++ 的 引用&

函数void Prim(MGraph g, int v0, int &sum)参数中的sumC++中的引用类型,表示它的值在传进函数以后,其值需要跟着函数的功能实现而被改变。


C++代码:  

#include <iostream>

using namespace std;

#define MAXSIZE 100
#define INF     500

typedef struct
{
    int no;
    char info;//
}VertexType;

typedef struct
{
    int n,e;
    int edges[MAXSIZE][MAXSIZE];
    VertexType vex[MAXSIZE];
}MGraph;

void Prim(MGraph g, int v0, int sum)
{
    int lowcost[g.n] = {0};
    int vset[g.n] = {0};
    int v;
    int i,j,k;
    int min;

    v = v0;
    vset[v] = 1;
    for(int i=0;i<g.n;++i)
        lowcost[i] = g.edges[v][i];
    sum = 0;

    for(int i=0;j<g.n-1;i++){
        min = INF;
        for(int j=0;j<g.n;++j)
            if(vset[j]==0 && lowcost[j] < min)
            {
                min = lowcost[j];
                k=j;
            }

        v = k;
        vset[v] = 1;
        sum += min;

        for(int j=0;j<g.n;++j)
            if(vset[j]==0 && g.edges[v][j]<lowcost[j])
                lowcost[j] = g.edges[v][j];
    }
}

int main()
{

}

程序的说明:

1. 

把一个很大的结构体MGraph作为函数的参数,浪费空间,这个在实际中需要改进。

作为考试代码,完全可以先这样写。

 

2.

外层的for循环,只需要执行g.n-1次(即 图的结点总数-1)即可,

因为参数v0表示MST的第一个起始结点,

又根据算法可以满足执行g.n-1次找到剩下的n-1个结点就完成MST的确定

 

3.

数组vset大小是图的结点个数,

初始化时元素都为0

随着算法的进行,如果某个结点i归入了MST,那么vset[i]置为1,否则为0

而程序中反复出现的判断语句vset[j]==0可以保证找到的树是一个不带环的图,这一点非常重要!!

待整个prim函数执行完,vset中的元素就会全部是1

 

4.

数组lowcost大小是图的结点个数,

这个变量记录的是当前MST 到 剩余其他结点 的 最小路径值

一开始MST只是结点V0

内层的第一个for循环用于使用当前的lowcost找到一个新的应该并入MST的结点v

内层的第二个for循环用于通过刚找到的这个新的并入MST的结点v更新lowcost

 

5.

外层循环执行g.n-1(简写为n-1)次,

内层的2for循环执行g.n(简写为n)次,

基本操作共执行(n-1*2n)次,

所以时间复杂度取大的量级为:n的平方,

也可以看出,Prim算法生成MST时间复杂度只与结点的个数有关,与边没有关系,

所以Prim算法适合 稠密图(结点多,边少)

 

6.

变量min表示

当前的MST树(中的各个节点)距离 剩下的 结点的 最小路径值 的 最小值

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值