对于任意一个连通网的最小生成树来说,在要求总的权值最小的情况下,最直接的想法就是将连通网中的所有边按照权值大小进行升序排序,从小到大依次选择。
1.任意定点之间只有一条通路,不能产生环
2.对于n个顶点的生成树只有n-1条通路即可
1.先将边按照边的权值排序
2.从小到大依次判断边,若加入该边不形成环,则将该边加入其中,反之,继续扫描下一条边
3.判断结束条件:加入的边为n-1条
如何判断是否成环?
//parent[i]表示i结点在已经生成树中可到达结点;
int Find(int x){
while(parent[x]>0){
x=parent[x];
} return x;
}
void Kruskal(){
int k=0,i=0;
printf("The lostpath:\n");
while(k<n-1){
int a=Find(sortedge[i].form); //获取已经排序边表中一端点的可到达端点a
int b=Find(sortedge[i].to); //获取已经排序边表中另一端点的可到达端点b
if(a!=b){//若ab不相同,则表示不能形成换
parent[a]=b;//将a的可到达端点设为b,以便判断下一条边是否形成环
//输出加入生成树的边
printf("%d %d %d\n",sortedge[i].form,sortedge[i].to,sortedge[i].weight);
k++;
}
i++;
}
}
#include
#include
#define N 20
#define inex 1001
int c[7][7]={ //用邻接表存储图结构,inex表示两端点不可达
{},
{inex,0,6,1,5,inex,inex},
{inex,6,0,5,inex,3,inex},
{inex,1,5,0,5,4,6},
{inex,5,inex,5,inex,inex,2},
{inex,inex,3,6,inex,0,6},
{inex,inex,inex,2,4,6,0},
};
typedef struct edge{ //构造有序图标数据结构
int form; //起始端点
int to; //目标端点
int weight;//两端点边的权值
}E;
E sortedge[101],t[101];//t用于排序,将结果赋值给sortedge
int parent[101]={};//判断是否成环的数据结构
int n=6;//端点数
int em(int k,int i,int j){//因为图为无相图,该函数判断是否该边已经加入变表
for(int z=0;z<k;z++){
if(sortedge[z].form==i&&sortedge[z].to==j){
return 0;
}
if(sortedge[z].form==j&&sortedge[z].to==i){
return 0;
}
}
return 1;
}
void sort(){//排序变表
int k=0;
E t;
for(int i=1;i<=n;i++){ //将所有边无重复的加入边表t中
for(int j=1;j<=n;j++){
if(c[i][j]>0&&c[i][j]<inex&&em(k,i,j)==1){
sortedge[k].form=i;
sortedge[k].to=j;
sortedge[k].weight=c[i][j];
k++;
}
}
}
for(int i=0;i<k;i++){ //选择法排序
int min=sortedge[i].weight;
int minid=i;
for(int j=i+1;j<k;j++){
if(sortedge[j].weight<min){
min=sortedge[j].weight;
minid=j;
}
}
t=sortedge[i];
sortedge[i]=sortedge[minid];
sortedge[minid]=t;
}
printf("\nThe edge after sorting:\n");
for(int i=0;i<k;i++){ //将排序结果赋值给 sortedge
printf("%d %d %d\n",sortedge[i].form,sortedge[i].to,sortedge[i].weight);
}
}
//parent[i]表示i结点在已经生成树中可到达结点;
int Find(int x){
while(parent[x]>0){
x=parent[x];
} return x;
}
void Kruskal(){
int k=0,i=0;
printf("The lostpath:\n");
while(k<n-1){
int a=Find(sortedge[i].form); //获取已经排序边表中一端点的可到达端点a
int b=Find(sortedge[i].to); //获取已经排序边表中另一端点的可到达端点b
if(a!=b){//若ab不相同,则表示不能形成换
parent[a]=b;//将a的可到达端点设为b,以便判断下一条边是否形成环
//输出加入生成树的边
printf("%d %d %d\n",sortedge[i].form,sortedge[i].to,sortedge[i].weight);
k++;
}
i++;
}
}
int main(){//主函数入口
sort();
Kruskal();
}