图的最小生成树(Prim算法)
前言
普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。
下面是Prim算法的实现
先实现Prim算法相关的结构
//邻接矩阵的数据类型
#define MAXV 50 //最大顶点数
#define INF 0xffff//表示无穷大
typedef struct
{
int edges[MAXV][MAXV];//邻接矩阵的边数组
int n, e;//顶点数,边数
}MGraph;//图邻接矩阵类型
Prim算法代码如下:
void Prim(MGraph g, int v)//Prim算法,v是开始的点,可以任意取一个
{
int lowcost[MAXV], closest[MAXV], i, min, j, k;
//为了便于选中当前权值最小的边的节点,需要建立两个数组closest和lowcost,
//对于某个未选中的节点j,lowcost[j]存储的是节点j与当前已选节点相连的最小权值(lowcost[j]==0表示节点j已被选)
//closest[j]存储lowcost[j]对应的连接点
for (i = 0; i < g.n; i++)//初始化lowcost数组,closest数组
{
closest[i] = v;
lowcost[i] = g.edges[v][i];
}
for (i = 1; i < g.n; i++)//接下来找剩下的n-1个节点
{
min = INF;//INF表示正无穷(每查找一个节点,min都会重新更新为INF,以便获取当前最小权重的节点)
for (j = 0; j < g.n; j++)//遍历所有节点
{
if (lowcost[j] != 0 && lowcost[j] < min)//若该节点还未被选且权值小于之前遍历所得到的最小值
{
min = lowcost[j];//更新min的值
k = j;//记录当前最小权重的节点的编号
}
}
printf("边(%d,%d)权为:%d\n", closest[k], k, min);//输出被连接节点与连接节点,以及它们的权值
//更新lowcost数组,closest数组
lowcost[k] = 0;//表明k节点已被选了(作标记)
//选中一个节点完成连接之后,作数组相应的调整
for (j = 0; j < g.n; j++)//遍历所有节点
{
if (g.edges[k][j] != 0 && g.edges[k][j] < lowcost[j])
{
//更新lowcost数组,closest数组
lowcost[j] = g.edges[k][j];//更新权重,使其当前最小
closest[j] = k;//刚选的节点k与当前节点j有更小的权重,则closest[j]的被连接节点需作修改为k.
}
}
}
}