Prim、Kruskal最小生成树

来源:互联网 发布:腐尸之屋 知乎 编辑:程序博客网 时间:2024/05/21 04:21

Prim:设置一个集合V,在图中取一个顶点为起点,加入到V中,从一个顶点在V中,另一个邻接顶点不在V中的所有条边中选择权值最小的边,加入到最小生成树,并将该邻接点加入到集合V中。重复上述过程,直到图中所有顶点加入到集合V中为止。

typedef struct Edges{int from;int to;int weight;};
Graphics *Prim(Graphics *gh){    Edges *arr[Maxsize];    Graphics *g=(Graphics*)malloc(sizeof(Graphics));if(NULL==g) {printf("Init Failed.\n");exit(1);}    bool joined[Maxsize];for(int i=0;i<gh->Vcount;i++){joined[i]=false;        VertexNode *vnode=(VertexNode*)malloc(sizeof(VertexNode));        if(NULL==vnode)     {    printf("Init Failed.\n");    exit(1);    }vnode->data=gh->graph[i]->data;vnode->link=NULL;g->graph[i]=vnode;}g->Vcount=gh->Vcount;int idx=0;int j=0;for(int i=1;i<gh->Vcount;){if(!joined[idx]){joined[idx]=true;  }EdgeNode *node=gh->graph[idx]->link;while(node!=NULL){Edges *edge=(Edges*)malloc(sizeof(Edges));if(edge==NULL){                printf("Init Failed.\n");        exit(1);}edge->from=idx;edge->to=node->indx;edge->weight=node->weight;            arr[j++]=edge;node=node->next;}        Edges *minedge=NULL;for(int k=0;k<j;k++){if(arr[k]!=NULL){                if(minedge==NULL)    minedge=arr[k];if(!joined[arr[k]->to]){if(arr[k]->weight<minedge->weight)minedge=arr[k];}else   {if(minedge==arr[k])minedge=NULL;arr[k]=NULL;}}}EdgeNode *newnode=(EdgeNode*)malloc(sizeof(EdgeNode));        if(newnode==NULL)    {             printf("Init Failed.\n");     exit(1);    }newnode->indx=minedge->to;newnode->weight=minedge->weight;newnode->next=g->graph[minedge->from]->link;g->graph[minedge->from]->link=newnode;        newnode=(EdgeNode*)malloc(sizeof(EdgeNode));        if(newnode==NULL)    {             printf("Init Failed.\n");     exit(1);    }newnode->indx=minedge->from;newnode->weight=minedge->weight;newnode->next=g->graph[minedge->to]->link;g->graph[minedge->to]->link=newnode;idx=minedge->to;i++;g->Ecount++;}return g;}
Kruskal:设置包含N个顶点,没有边的非连通图,其中每个顶点自成一个连通分量。选到一条最小权值的边时,若该边的两个顶点不在同一个连通分量,不构成环路,则将该边加入,否则舍去,重新选择一条权值最小的边。重复上述过程,直到找到N-1条边为止。

判断环,设置一个结构体数组:

typedef struct Unionset{int vnode;Unionset *parent;};
每找到一条权值最小的边,先判断该边的两个顶点的祖先是否相同,不同,则该加入该边不构成环路,然后把边的一个顶点的祖先指向边的另一个顶点;否则,舍去。

Graphics *Kruskal(Graphics *gh){int i=0;int j=0;    Unionset *_union[Maxsize];    Edges *edges[Maxsize];if(NULL==gh||gh->Vcount<=0) return NULL;    Graphics *g=(Graphics*)malloc(sizeof(Graphics));if(g==NULL){        printf("Init Failed.\n");exit(1);}    for(;i<gh->Vcount;i++){        Unionset *u=(Unionset*)malloc(sizeof(Unionset));if(NULL==u){             printf("Init Failed.\n");     exit(1);}u->parent=NULL;u->vnode=i;_union[i]=u;VertexNode *vnode=(VertexNode*)malloc(sizeof(VertexNode));        if(NULL==vnode)     {    printf("Init Failed.\n");    exit(1);    }vnode->data=gh->graph[i]->data;vnode->link=NULL;g->graph[i]=vnode;}g->Vcount=gh->Vcount;//排序for(i=0;i<gh->Ecount-1;i++){for(j=0;j<gh->Ecount-1-i;j++){if(gh->_edges[j]->weight>gh->_edges[j+1]->weight){Edges *tmp=gh->_edges[j];gh->_edges[j]=gh->_edges[j+1];gh->_edges[j+1]=tmp;}}}for(j=i=0;i<gh->Vcount-1;j++){Edges *edge=gh->_edges[j];  //找出权最小的边//判断是否成环Unionset *ufrom_parent=_union[edge->from];Unionset *uto_parent=_union[edge->to];Unionset *temp=ufrom_parent->parent;        while(temp!=NULL){ufrom_parent=temp;temp=temp->parent;}temp=uto_parent->parent;while(temp!=NULL){uto_parent=temp;temp=temp->parent;}        if(ufrom_parent!=uto_parent){            EdgeNode *enode=(EdgeNode*)malloc(sizeof(EdgeNode));enode->indx=edge->to;enode->next=g->graph[edge->from]->link;            g->graph[edge->from]->link=enode;enode->weight=edge->weight;            enode=(EdgeNode*)malloc(sizeof(EdgeNode));enode->indx=edge->from;enode->next=g->graph[edge->to]->link;g->graph[edge->to]->link=enode;enode->weight=edge->weight;uto_parent->parent=_union[edge->from];i++;}}g->Ecount=i;return g;}




0 0
原创粉丝点击