/*请把这个例子和Dijkstra算法一起看,会发现他们几乎一模一样有木有!*/
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
#define inf 65535
void prim(int c[][7],int n,int lowcost[],int closest[])//c是邻接矩阵,n为顶点个数,i从2到6,因为prim算法的初始顶点是任意的,索性就取顶点1作为初始顶点
{ //lowcost[i]代表一轮V-S中的顶点i到S的所有点中最小的距离值,closest[i]表示每一轮每个顶点i到集合S中对应距离的最小值的那个顶点,即边i-closest[i]是针对i来说到集合S所有点的距离中最小的那个边
int s[7];//s判断顶点是否在S中,如果在就是1,不在就是0
for(int i=2;i<=n;i++)//初始化,除1之外的所有的点的lowcost[]都是直接与顶点1的距离
{
lowcost[i]=c[1][i];
closest[i]=1;//同时,closest[]初始化为1,毕竟此时S中只剩1号一个
s[i]=0;//现在顶点2到顶点6均未加入S阵营
}
s[1]=1;//S中现在只剩1号一个
for(int i=1;i<=n-1;i++)//开始迭代,迭代次数为n-1
{
int min=inf,j;//min和j用于记录每轮各个顶点(i从2到6)lowcost[i]的最小值,j用于记录顶点号
for(int k=2;k<=n;k++)//开始寻找最小值和最小值对应的顶点号了,这就是简单的擂台赛
if(!s[k]&&lowcost[k]<min)
{
min=lowcost[k];
j=k;
}
s[j]=1;//此时lowcost[i]的最小值对应的顶点号是j,那么就要把顶点j加入S集合中
for(int k=2;k<=n;k++)//顶点j加入了,此时需要修改现在的V-S阵营中每个顶点的lowcost[]和closest[]值,因为S发生了变化,因此相应的就需要改变
if(!s[k]&&c[j][k]<lowcost[k])//如果发现还有更小的,就更新lowcost[]和closest[]值,注意两个都要更新,不能只更新一个!
{
lowcost[k]=c[j][k];
closest[k]=j;
}
}
}
void print(int lowcost[],int closest[],int n)//打印结果
{
for(int i=2;i<=n;i++)
cout<<i<<"--"<<closest[i]<<":"<<lowcost[i]<<endl;
}
int main()
{
int c[7][7]={ //因为我的顶点号是从1开始的,一共6个顶点,所以我申请了一个7×7的矩阵,下标为0的地方我设置成无穷大,不影响最后结果
{inf,inf,inf,inf,inf,inf,inf},
{inf,inf,6,1,5,inf,inf},
{inf,6,inf,5,inf,3,inf},
{inf,1,5,inf,5,6,4},
{inf,5,inf,5,inf,inf,2},
{inf,inf,3,6,inf,inf,6},
{inf,inf,inf,4,2,6,inf},
};
int lowcost[7],closest[7];
prim(c,6,lowcost,closest);
print(lowcost,closest,6);
}
普里姆算法(最小生成树)
最新推荐文章于 2024-06-23 15:37:17 发布