这里的最小生成树是指无向图的
每条边有大于0的整数的权值
这里有2种算法
一个为PRIM 这个算法时间要 O(n2)
另一个算法为Kruskal算法时间为O(elog2e)
但是这里还有个潜在的排序要实现,我这里排序并没有用好的算法
主要是为了实现Kruskal的思想
其排序的一些算法将在后续推出
#include <stdio.h>
#define MAX 100
#define INF 32767
void prim(int cost[][MAX],int ver,int v)
... {
int i,j,k;
int min;
int lowcost[MAX][2];
for(i=0;i<ver;i++)
...{
lowcost[i][1]=v; //这里是指这条边是由谁为起点的
lowcost[i][0]=cost[v][i]; //这是这条边的权值
if(i==v)
lowcost[i][1]=-1;
}
for(i=0;i<ver-1;i++)
...{
min=INF;
for(j=0;j<ver;j++)
...{
if(lowcost[j][1]!=-1&&lowcost[j][0]<min&&lowcost[j][0]!=0) //寻找最小权值可用的边
...{
min=lowcost[j][0];
k=j;
}
}
printf("%d---->%d cost %d ",lowcost[k][1],k,min);
lowcost[k][1]=-1;
for(j=0;j<ver;j++) //修改 lowcost 把新加进来的点的更短的边替换原来的边
...{
if(lowcost[j][1]!=-1&&(lowcost[j][0]>cost[k][j]&&cost[k][j]!=0||lowcost[j][0]==0))
...{
lowcost[j][0]=cost[k][j];
lowcost[j][1]=k;
}
}
}
}
void Kruskal(int cost[][MAX],int ver,int v)
... {
int edge[MAX][3];
int vset[MAX];
int i,j,k;
int a,b,c,t;
int min;
//这里用最简单的快排来 实际可以用更快的排序
k=-1;
for(i=0;i<ver;i++)
...{
vset[i]=i;
for(j=i;j<ver;j++)
...{
if(cost[i][j]!=0)
...{
k++;
edge[k][0]=i;
edge[k][1]=j;
edge[k][2]=cost[i][j];
}
}
}
for(i=0;i<k;i++)
...{
min=edge[i][2];
t=i;
for(j=i+1;j<k;j++)
...{
if(edge[j][2]<min)
...{
t=j;
min=edge[j][2];
}
}
if(t!=i)
...{
a=edge[i][0];b=edge[i][1];c=edge[i][2];
edge[i][0]=edge[t][0];edge[i][1]=edge[t][1];edge[i][2]=edge[t][2];
edge[t][0]=a;edge[t][1]=b;edge[t][2]=c;
}
}
// 到这里都是为了排序 其实可以用更好的方法来写 这里比较懒就将就下
k=1;
i=0;
while(i<ver)
...{
if(vset[edge[i][0]]!=vset[edge[i][1]]) //vset为集合 这里不同的边选出来后会有不同的集合
...{
printf("%d-->%d cost is %d ",edge[i][0],edge[i][1],edge[i][2]);
for(j=0;j<ver;j++)
if(vset[j]==vset[edge[i][1]])
vset[j]=vset[edge[i][0]];
k++;
}
i++;
}
}
int main()
... {
int cost[MAX][MAX];
int i,j;
int a,b,c;
int ver,arc;
for(i=0;i<MAX;i++)
for(j=0;j<MAX;j++)
cost[i][j]=0;
printf("input the ver and arc ");
scanf("%d %d",&ver,&arc);
for(i=0;i<arc;i++)
...{
scanf("%d %d %d",&a,&b,&c);
cost[a][b]=c;
cost[b][a]=c;
}
for(i=0;i<ver;i++)
...{
for(j=0;j<ver;j++)
printf("%d",cost[i][j]);
printf(" ");
}
prim(cost,ver,0);
Kruskal(cost,ver,0);
return 0;
}
#define MAX 100
#define INF 32767
void prim(int cost[][MAX],int ver,int v)
... {
int i,j,k;
int min;
int lowcost[MAX][2];
for(i=0;i<ver;i++)
...{
lowcost[i][1]=v; //这里是指这条边是由谁为起点的
lowcost[i][0]=cost[v][i]; //这是这条边的权值
if(i==v)
lowcost[i][1]=-1;
}
for(i=0;i<ver-1;i++)
...{
min=INF;
for(j=0;j<ver;j++)
...{
if(lowcost[j][1]!=-1&&lowcost[j][0]<min&&lowcost[j][0]!=0) //寻找最小权值可用的边
...{
min=lowcost[j][0];
k=j;
}
}
printf("%d---->%d cost %d ",lowcost[k][1],k,min);
lowcost[k][1]=-1;
for(j=0;j<ver;j++) //修改 lowcost 把新加进来的点的更短的边替换原来的边
...{
if(lowcost[j][1]!=-1&&(lowcost[j][0]>cost[k][j]&&cost[k][j]!=0||lowcost[j][0]==0))
...{
lowcost[j][0]=cost[k][j];
lowcost[j][1]=k;
}
}
}
}
void Kruskal(int cost[][MAX],int ver,int v)
... {
int edge[MAX][3];
int vset[MAX];
int i,j,k;
int a,b,c,t;
int min;
//这里用最简单的快排来 实际可以用更快的排序
k=-1;
for(i=0;i<ver;i++)
...{
vset[i]=i;
for(j=i;j<ver;j++)
...{
if(cost[i][j]!=0)
...{
k++;
edge[k][0]=i;
edge[k][1]=j;
edge[k][2]=cost[i][j];
}
}
}
for(i=0;i<k;i++)
...{
min=edge[i][2];
t=i;
for(j=i+1;j<k;j++)
...{
if(edge[j][2]<min)
...{
t=j;
min=edge[j][2];
}
}
if(t!=i)
...{
a=edge[i][0];b=edge[i][1];c=edge[i][2];
edge[i][0]=edge[t][0];edge[i][1]=edge[t][1];edge[i][2]=edge[t][2];
edge[t][0]=a;edge[t][1]=b;edge[t][2]=c;
}
}
// 到这里都是为了排序 其实可以用更好的方法来写 这里比较懒就将就下
k=1;
i=0;
while(i<ver)
...{
if(vset[edge[i][0]]!=vset[edge[i][1]]) //vset为集合 这里不同的边选出来后会有不同的集合
...{
printf("%d-->%d cost is %d ",edge[i][0],edge[i][1],edge[i][2]);
for(j=0;j<ver;j++)
if(vset[j]==vset[edge[i][1]])
vset[j]=vset[edge[i][0]];
k++;
}
i++;
}
}
int main()
... {
int cost[MAX][MAX];
int i,j;
int a,b,c;
int ver,arc;
for(i=0;i<MAX;i++)
for(j=0;j<MAX;j++)
cost[i][j]=0;
printf("input the ver and arc ");
scanf("%d %d",&ver,&arc);
for(i=0;i<arc;i++)
...{
scanf("%d %d %d",&a,&b,&c);
cost[a][b]=c;
cost[b][a]=c;
}
for(i=0;i<ver;i++)
...{
for(j=0;j<ver;j++)
printf("%d",cost[i][j]);
printf(" ");
}
prim(cost,ver,0);
Kruskal(cost,ver,0);
return 0;
}