算法:Prim
应用:对一个带权无向图生成 (权值)最小生成树
(程序来自《天勤 数据结构 高分笔记》)
今日一签,赠给奋斗的自己和你们:
讲述算法前,先做如下的说明:
1. 带权无向图的存储
把一个共有N个结点的带权无向图的信息(边以及边的权值)存放在一个大小为N乘N的二维方阵中。
带权无向图的N个结点的编号是0至N-1。
方阵元素[i][j]表示节点编号是i和j的2个节点之间的边的权值,
行标 = 列标 的 方阵元素 规定 其值是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)参数中的sum是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)次,
内层的2个for循环执行g.n(简写为n)次,
基本操作共执行(n-1)*(2n)次,
所以时间复杂度取大的量级为:n的平方,
也可以看出,Prim算法生成MST时间复杂度只与结点的个数有关,与边没有关系,
所以Prim算法适合 稠密图(结点多,边少)
6.
变量min表示
当前的MST树(中的各个节点)距离 剩下的 结点的 最小路径值 的 最小值