算法原理
假设G=(V,E)为一无向连通图,其中V是网中顶点的集合,E为网中边的集合
设置两个新的集合U和T,其中,U为G的最小生成树的顶点的集合,T为G的最小生成树的边的集合
令集合U的初值为U={u1}(假设构造最小生成树时从顶点u1开始),集合T的处置为T={}。
从所有的顶点u∈U和顶点v∈V-U的带权边中选出具有最小权值的边(u,v)
将顶点v加入集合U中,将边(u,v)加入集合T中。如此不断地重复直到U=V时时最小生成树构造完毕。
此时,集合U中存放着最小生成树的所有顶点,集合T中存放着最小生成树的所有边
算法代码详解
1.声明两个数组和一个整型变量,分别是权值数组lowcost,根据邻接矩阵得到当前顶点和其他顶点的权值。顶点数组closevex,存储最终得到的最小生成树的顶点数组,最小花费mincost,用于筛选权值最小的顶点。
int[] lowcost = new int[nodes.Length];
int[] closevex = new int[nodes.Length];
int mincost = int.MaxValue;
2.初始化两个数组。权值数组的成员为选定的数组索引为0的顶点到所有顶点的权值。
顶点数组为0
for(int i = 1; i < nodes.Length; i++)
{
lowcost[i] = matrix[0, i];
closevex[i] = 0;
}
3.使第一个顶点A的权值数组值为0,表示该顶点已加入集合U
lowcost[0] = 0;
closevex[0] = 0;
4.for循环遍历权值数组,即遍历A到其它顶点的边的权值,while循环中如果有比最小花费小的权值,得到该顶点B的索引k,while循环结束后,使顶点B在权值数组中为0,表示顶点B加入集合U。第二层for循环中,如果顶点B与顶点C的边的权值小于权值数组中A-C的对应权值。就使权值数组的A-C边权值改为B-C边权值,即更新A到各顶点的边的权值(我认为是其他顶点到集合U里顶点中最小的权值),并将下标为k的顶点存入生成树的顶点数组
for(int i = 0; i < nodes.Length; i++){
int k = 1, j = 1;
while (j < nodes.Length){//循环全部节点
if (lowcost[j] < mincost && lowcost[j] != 0){
mincost = lowcost[j];//更新最小的权值
k = j;//将最小权值的下标存入k
}
++j;
}
lowcost[k] = 0;//该顶点进入集合U,完成任务
for (j = 1; j < nodes.Length; j++){
if (matrix[k, j] < lowcost[j] && lowcost[j] != 0){
//若下标为k的顶点对应的各个顶点的权值小于这些顶点未被加入生成树时的权值
lowcost[j] = matrix[k, j];//将较小的权值存入lowcost数组
closevex[j] = k;//将下标为k的顶点存入生成树的顶点数组
}
}
}
完整的Prim算法实现
public int[] Prim()
{
int[] lowcost = new int[nodes.Length];
int[] closevex = new int[nodes.Length];
int mincost = int.MaxValue;
for(int i = 1; i < nodes.Length; i++)
{
lowcost[i] = matrix[0, i];
closevex[i] = 0;
}
lowcost[0] = 0;
closevex[0] = 0;
for(int i = 0; i < nodes.Length; i++)
{
int k = 1;
int j = 1;
while (j < nodes.Length)
{
if (lowcost[j] < mincost && lowcost[j] != 0)
{
k = j;
}
++j;
}
lowcost[k] = 0;
for (j = 1; j < nodes.Length; j++)
{
if (matrix[k, j] < lowcost[j])
{
lowcost[j] = matrix[k, j];
closevex[j] = k;
}
}
}
return closevex;
}