Kruskal算法
1.首先将G的n个顶点看成n个孤立的连通分支,将所有的边按权从小到大排序e1,e2,e3...em
2.从第一条边开始,依边权递增的顺序查看每一条边,并按下述方法连接两个不同的两同分支
3.当查看到第K条边ek=(v,w)时,若v,w分别在两个不同而连通分支T1和T2中,用边(v,w)将T1,T2连接成一个连通分支,然后继续查看k+1条边
若v和w在当前的同一个连通分支中,就直接查看第k+1条边(既构成圈,就放弃ek)
这个过程一直进行到之剩下一个连通分支时为止。此时,这个连通分支就是G的一颗最小生成树了
View Code
#include<iostream> using namespace std; struct NODE{//记录边及边的端点 int edge; int x,y; }; int compare(const void *b1,const void *b2){ NODE *aa=(NODE *)b1; NODE *bb=(NODE *)b2; return((aa->edge)-(bb->edge)); } void Kruskal(int n,int m,NODE *Edge){ int i,j,u,v,temp1,temp2,parts=0; int *vertex=new int[n+1];//用vertex进行集合操作 qsort(Edge+1,m,sizeof(NODE),compare); for(i=1;i<=n;i++) vertex[i]=0;//用数组vertes来进行集合操作 for(i=1;i<=m;i++){ u=Edge[i].x; v=Edge[i].y;//第i条边的端点u,v if(!vertex[u]&&!vertex[v]){ parts++;//增加一个分支 vertex[u]=parts;//添加边u vertex[v]=parts;//添加边v cout<<u<<" "<<v<<endl; } else if(vertex[u]&&!vertex[v]){//如果点u已处理而点v未处理原始状态 parts++;//增加一分支 vertex[v]=vertex[u];//将变(u,v) 加入到v所在的支 cout<<u<<" "<<v<<endl; } else if(!vertex[u]&&vertex[v]){// 如果点v已处理而点u未处理原始状态 parts++; vertex[u]=vertex[v]; cout<<u<<" "<<v<<endl; } else if(vertex[u]!=vertex[v]){//如果u和v处于不同的支 cout<<u<<" "<<v<<endl; temp1=vertex[u]; temp2=vertex[v]; if(vertex[u]>vertex[v]){ temp1=vertex[v]; temp2=vertex[u]; } for(j=1;j<=m;j++){ if(vertex[j]==temp2)//缩小,调整到较小标号的支 vertex[j]=temp1; else if(vertex[j]>temp1) vertex[j]--; } parts--;//分支数减少1 } } delete vertex; } int main(){ int n,m; int i; NODE *Edge; cout<<"请输入顶点个数和边数:"; cin>>n>>m; Edge=new NODE[m+1]; cout<<"两顶点的序号和连接他们的边的权值:"<<endl; for(i=1;i<=m;i++) cin>>Edge[i].x>>Edge[i].y>>Edge[i].edge; cout<<"最小生成树连接情况:"<<endl; Kruskal(n,m,Edge); delete Edge; return 0; }