克鲁斯卡尔&普里姆算法都在代码之中
#include<iostream>
#include<stdlib.h>
#define False 0
#define True 1
using namespace std;
typedef struct
{
int pointvertexmyself_i;/*pointvertexmyself_i 这个顶点是和本顶点向连接的顶点*/
int lowcost;/*记录pointvertexmyself_i 和 本顶点的边的权值*/
}Closedge;
Closedge closedge[100];/*全局变量用来记录V-U中边的权值*/
typedef struct/*定义三元组*/
{
int startvertex;/*开始顶点*/
int endvertex;/*结束顶点*/
int adjacent;/*权值*/
}Triple;
typedef struct/*定义图的结构体*/
{
Triple triple[10000];
int vertexnumber;
int count;
}Graph;
int Miniclosedge(Graph G)/*求V-U中权值最小的边*/
{
int cost=999999,u=1;
for(int i=1;i<=G.vertexnumber;i++)/*进行循环比较得到最小权值变的下边u*/
{
if(closedge[i].lowcost<cost&&closedge[i].lowcost!=0)
{
u=i;
cost=closedge[i].lowcost;
}
}
return u;
}
int MiniSpanTreePrim(Graph G,int u)/*普里姆算法*/
{
int sum=0;/*记录最小生成树的权值的和*/
int t;
for(int i=1;i<=G.vertexnumber;i++)/*初始化closedge*/
{
closedge[i].pointvertexmyself_i=u;
closedge[i].lowcost=999999;
}
closedge[u].lowcost=0;
for(int j=1;j<=G.count;j++)/*将所知道的变得权值赋给closedge
因为本体是用无向图所以要进行两次:一次是“去 ”一次是“回 ”*/
if(G.triple[j].startvertex==u)
{
closedge[G.triple[j].endvertex].pointvertexmyself_i=u;
closedge[G.triple[j].endvertex].lowcost=G.triple[j].adjacent;
}
else if(G.triple[j].endvertex==u)
{
closedge[G.triple[j].startvertex].pointvertexmyself_i=u;
closedge[G.triple[j].startvertex].lowcost=G.triple[j].adjacent;
}
else;
for(int k=1;k<=G.vertexnumber-1;k++)/*得到最小生成树的n-1条边*/
{
t=Miniclosedge(G);/*得到最小权值边在closedge中的下标t*/
u=closedge[t].pointvertexmyself_i;/*得到相连的顶点*/
sum+=closedge[t].lowcost;/*将边的值加入sum*/
closedge[t].lowcost=0;
for(int i=1;i<=G.count;i++)/*更新closedge数组也要“有去有回 ”*/
{
if(G.triple[i].startvertex==t&&G.triple[i].adjacent<closedge[G.triple[i].endvertex].lowcost)
{
closedge[G.triple[i].endvertex].lowcost=G.triple[i].adjacent;
closedge[G.triple[i].endvertex].pointvertexmyself_i=t;
}
else if(G.triple[i].endvertex==t&&G.triple[i].adjacent<closedge[G.triple[i].startvertex].lowcost)
{
closedge[G.triple[i].startvertex].lowcost=G.triple[i].adjacent;
closedge[G.triple[i].startvertex].pointvertexmyself_i=t;
}
}
}
return sum;
}
int GetminiEdge(Graph G,int *vest)/*得到权值最小的边 因为不能形成环 所以有vest数组 vest数组是记录哪些点已经在集合U中当
U=V是vest中的数据全部为1 即: 所有点都已经背访问过了且在集合U中*/
{
int k;
for(int i=1;i<=G.count;i++)
{/*确保两个点在不同的集合中 因为如果在同一个集合中会构成环或者不能连通*/
if((vest[G.triple[i].startvertex]==0&&vest[G.triple[i].endvertex]==1)||(vest[G.triple[i].startvertex]==1&&vest[G.triple[i].endvertex]==0))
{
k=i;
vest[G.triple[i].startvertex]=1;
vest[G.triple[i].endvertex]=1;
break;
}
}
return k;/*因为G已经按边的权值排序了 因此K就是下一个最小的边在G.triple的下标值*/
}
int MinniSpanKuscal(Graph G)/*克鲁斯卡尔算法*/
{
int *vest,sum=0;/*vest数组的作用已经在上面说明 sum的作用也同上*/
vest=(int *)malloc(sizeof(int)*G.vertexnumber+1);/*动态申请空间*/
for(int i=0;i<=G.vertexnumber;i++)
vest[i]=0;/*因为所有的顶点都没有访问所以都赋值为0*/
for(int i=1;i<=G.count;i++)/*对G.triple按边的权值进行排序(从小到大排序)*/
for(int j=i;j<=G.count;j++)
{
if(G.triple[i].adjacent>G.triple[j].adjacent)
{
int a,b,c;/*交换信息*/
a=G.triple[i].adjacent;b=G.triple[i].endvertex;c=G.triple[i].startvertex;
G.triple[i].adjacent=G.triple[j].adjacent;
G.triple[i].endvertex=G.triple[j].endvertex;
G.triple[i].startvertex=G.triple[j].startvertex;
G.triple[j].adjacent=a;G.triple[j].endvertex=b;G.triple[j].startvertex=c;
}
}
vest[G.triple[1].startvertex]=1;/*第一条边是最小的 因此访问最小边的顶点*/
vest[G.triple[1].endvertex]=1;
sum+=G.triple[1].adjacent;
for(int i=1;i<G.vertexnumber-1;i++)/*得到剩下的n-2条边*/
{
int t=GetminiEdge(G,vest);
sum+=G.triple[t].adjacent;
}
free(vest);
return sum;
}
int main()
{
Graph G;/*创建一个图*/
cin>>G.vertexnumber>>G.count;
for(int i=1;i<=G.count;i++)/*输入边的信息*/
{
cin>>G.triple[i].startvertex;
cin>>G.triple[i].endvertex;
cin>>G.triple[i].adjacent;
}
int u=1,minisum;
minisum=MiniSpanTreePrim(G,u);/*普里姆算法*/
cout<<minisum<<endl;
minisum=MinniSpanKuscal(G);/*克鲁斯卡尔算法*/
cout<<minisum;
return 0;
}