Kruskal算法
伪码描述:
void Kruskal( Graph G ) {
MST = { } ; //MST用邻接表
while( MST 中不到|V| -1 条边&& E 中还有边) {
从E 中取一条权重最小的边E(v,w) ;
将E(v,w)从E 中删除;
if( E(V,W)不在MST 中构成回路) 将E(V,W)加入MST;
else 彻底无视E(V,W); }
if( MST 中不到|V| 1 条边) Error ( “生成树不存在”);
}
Part 1——并查集
void InitializeVSet(int N,SetType VSet)
{
for(int i=0;i<N;i++) VSet[i]=-1; ///N个集合,下标从0开始
}
int Find(Vertex X,SetType VSet)//找顶点集合
{
if(VSet[X]<0) return X;//
else return VSet[X]=Find(VSet[X],VSet);//压缩路径
}
void Union(SetType VSet,int root1,int root2)
{
if(VSet[root1]<VSet[root2]){//小的并入大的
VSet[root1]+=VSet[root2];
VSet[root2]=root1; }
else{
VSet[root2]+=VSet[root1];
VSet[root1]=root2; }
}
int check(SetType VSet,Vertex v1,Vertex v2)
{
int root1,root2;
root1=Find(v1,VSet);root2=Find(v2,VSet);
if(root1==root2) return -1;
else{
Union(VSet,root1,root2);
return 1; }
}
Part 2——最小堆
void percDown(Edge ESet,int p,int N)//找顶点p的正确位置
{
int parent,child;
struct ENode X;X=ESet[p];
for(parent=p;(parent*2+1)<N;parent=child){///堆从0开始 ,注意堆中parent和child的标号关系
child=parent*2+1;
if(child!=N-1&&ESet[child+1].weight<ESet[child].weight) child=child+1;
if(ESet[child].weight<X.weight) ESet[parent]=ESet[child];/
else break; }
ESet[parent]=X;
}
void InitializeESet(LGraph Graph,Edge ESet)//将图中边输入到ESet中 无向边
{
int ECount=0;
int i;
for(i=0;i<Graph->Nv;i++){
for(PtrA w=Graph->G[i].FirstEdge;w;w=w->next)
if(i<w->AdjV){
ESet[ECount].v1=i;ESet[ECount].v2=w->AdjV;
ESet[ECount++].weight=w->weight;}
}
for(ECount=(Graph->Ne-2)/2;ECount>=0;ECount--) percDown(ESet,ECount,Graph->Ne);
}
int GetMin(Edge ESet,int currentsize)
{
struct ENode tmp;
tmp=ESet[0];
ESet[0]=ESet[currentsize-1];
ESet[currentsize-1]=tmp;
percDown(ESet,0,currentsize-1);
return currentsize-1;
}
Part 3——Kruskal
int Kurskal(LGraph Graph,LGraph MST)//返回最终权重
{
weightType Totalweight;
int ECount;//MST中收录边数
int currentsize;//边集数
MST=createG(Graph->Nv);
Edge ESet;
ESet=(Edge)malloc(sizeof(struct ENode)*Graph->Ne);//!
~~我是初始化分界线~~
InitializeESet(Graph,ESet);//初始化边集
SetType VSet;
InitializeVSet(Graph->Nv,VSet);//初始化顶点并查集
ECount=0;
Totalweight=0;
currentsize=Graph->Ne;
while(ECount<Graph->Nv-1){
currentsize=GetMin(ESet,currentsize);//最小权重边位置
if(currentsize<0) break;
if(check(VSet,ESet[currentsize].v1,ESet[currentsize].v2)==1) {
Insert(MST,ESet+currentsize);
Totalweight+=ESet[currentsize].weight;
ECount++; }
}
if(ECount!=Graph->Nv-1) return -1;
else return Totalweight;
}