Prim算法是建立在贪心算法的基础上的算法,主要思想就是每次都去找已访问的顶点连向未访问的顶点中最短的边。
算法思路:
1.u集合存放所有最短边的起始点,lowcost存放待选边(每次选择最小边都从lowcost中选出);
2.初始先将u的值都设置为入口点start,将lowcost的待选边都设置为入口点start的相邻边;
3.从lowcost选出一条没有访问过的最短边,并得到它的终点;
4.将终点的相邻边与lowcost做对比,保存更短的边,并更新起点集合u;
5.重复执行3,4步骤,知道找完所有边生成最小树。
static int Prim(int[,] adjmatrix, int start)
{
int sum = 0;
int lenth = adjmatrix.GetLength(0);
int[] u = new int[lenth]; //每条最小边的起点
int[] lowcost = new int[lenth]; //待选边的权值集合(记录到每个顶点的权值)
//将初始的树集合和待选边全设为起点
for (int i = 0; i < lenth; i++)
{
u[i] = start;
lowcost[i] = adjmatrix[start, i];
}
lowcost[start] = -1; //值为0和-1的待选边不考虑(不考虑已用过的边和无法到达的边)
for (int i = 0; i < lenth; i++)
{
int min = int.MaxValue;
int k = -1;
//从待选边中找出一条最小的,并记录j(边的终点)
for (int j = 0; j < lenth; j++)
{
if (lowcost[j] > 0 && min > lowcost[j])
{
min = lowcost[j];
k = j;
}
}
//若找到了一条最小边
if (k != -1)
{
Console.WriteLine("{0}.从{1}到{2},距离为{3}", i, u[k], k, min);
lowcost[k] = -1; //将已使用的边排除
sum += min; //累加权值
//遍历顶点k(新加入的点)的相邻边,若有更小的就去更新待选边(这样能保证每次选择的边是最小边)
for (int j = 0; j < lenth; j++)
{
if (lowcost[j] == 0 || (adjmatrix[k, j] > 0 && adjmatrix[k, j] < lowcost[j]))
{
lowcost[j] = adjmatrix[k, j];
u[j] = k; //更新起点
}
}
}
}
return sum;
}