数据结构学习——最小生成树

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;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值