Kruskal思想:对G<V,E>来说,初始时的最小树集合T<V,0>无边,只有|V|个顶点;
不断地从集合E中选出在T中不构成回路,且边权最小的边;
直到集合T中边的数目为|V|-1;或者 T的连通分支为1 。
Kruskal算法实现步骤:
1.根据邻接矩阵初始化边<结构体数组>的信息,置连通分支个数为|V|;
2.当前连通分支个数为1时,结束。否则,从<E-T-U>中选择边权最小的边e;{U是当前会构成回路的边的集合}
3.判断新加入的边是否构成回路,若是,修改U集合,转2 ;否则,加入T中。
******************/
#include<iostream>
#define N 6
#define NUM 100
#define MAX 1000
using namespace std;
int edge[N][N]={{MAX,6,1,5,MAX,MAX},
{6,MAX,5,MAX,3,MAX},
{1,5,MAX,5,6,4},
{5,MAX,5,MAX,MAX,2},
{MAX,3,6,MAX,MAX,6},
{MAX,MAX,4,2,6,MAX}};
struct EDGE{
int v1;//边起点
int v2;//边终点
int val;//边权
}e[NUM];
int edge_num=0; //存储边数
int con[N];//存储图的连通情况
int cnt=N; //存储图的连通度
int status[NUM]={0};//边的状态<-1表示此边加入会构成回路,被舍弃;0表示此边暂未被处理;1表示此边已在最小树中>
bool Union(int a, int b)
{
int i;
int beg_degree=con[a];
int end_degree=con[b];
if(con[a]!=con[b]){
--cnt;//此时连通度减一
for(i=0; i<N; ++i)
if(con[i]==beg_degree ||con[i]==end_degree){
con[i]=cnt;
}
return true;
}
else return false;
}
void Kruskal()
{
int i, j;
int min, num=0;
int temp_v1, temp_v2, temp;
// temp_v1存储边的起点
//temp_v2存储边的终点
//temp存储边的序号
//初始化连通度 ,此时一个顶点就是一个连通分支
for(i=0; i<N; ++i)
con[i]=N+i;
while(num<N-1){//最小树的边的数目num小于{顶点数-1}时就一直执行
min=MAX;
for(j=0; j<edge_num; ++j)
if(min>e[j].val && status[j]==0){
temp_v1=e[j].v1;
temp_v2=e[j].v2;
min=e[j].val;
temp=j;
}
if(Union(temp_v1, temp_v2)){
status[temp]=1;
++num;
}
else{
status[temp]=-1;
}
}
}
int main()
{
int i, j;
for(i=0; i<N; ++i)
for(j=0; j<N; ++j)
if(edge[i][j]!=MAX){
e[edge_num].v1=i;
e[edge_num].v2=j;
e[edge_num].val=edge[i][j];
++edge_num;
}
Kruskal();
cout<<"最小生成树:"<<endl;
cout<<"起点|终点|边权"<<endl;
for(i=0; i<edge_num; ++i){
if(status[i]==1){
cout<<e[i].v1+1<<" "<<e[i].v2+1<<" "<<e[i].val<<endl;
}
}
system("pause");
return 0;
}