一步一步复习数据结构和算法基础--kruskal算法

来源:互联网 发布:js 改变窗口大小 编辑:程序博客网 时间:2024/05/22 05:06

MST--krukal 

kruakal算法和prim算法相比理解起来比较容易,而且也容易编程实现。

kruskal算法的是选择最小权值的边来构造最小生成树,当然要防止在构造最小生成树的时候形成环,这个可以通过并查集来实现。


1、对所有的边按照权值升序排列。

2、从权值最小的边开始选择,加入到边集合的数组中。同时处理并查集数组。

3、依次选择其他边,如果选择的边在并查集中属于同一集合就抛弃,否则加入边集合数组中。

4、所有的边选取完毕,同时最小生成树也构造完毕。

#include<stdio.h>#include<stdlib.h>#include<string.h>#define number 20#define MAX 99999typedef struct Edge{int info;int begin,end;}Edge;typedef struct node{int info;//图的节点存放的信息,可随时变动}GraphNode;typedef struct{GraphNode matrix[number+1][number+1];//构造邻接矩阵int vexs[number+1];//顶点向量int vertex,edge;//顶点个数、弧个数}Graph;int cmp(const void *a,const void *b){return (*((Edge*)a)).info - (*((Edge*)b)).info;}//创建图void CreatGraph(Graph *G){int i,k;int x,y,data;int vertex,edge;printf("输入图的顶点个数和边的个数.\n");scanf("%d%d",&vertex,&edge);G->vertex = vertex;G->edge = edge;printf("输入图的每个顶点.\n");for(i=1;i<=vertex;i++)scanf("%d",&G->vexs[i]);for(i=1;i<=vertex;i++)for(k=1;k<=vertex;k++)G->matrix[i][k].info = MAX;printf("请输入 %d 条边的横坐标、纵坐标、数值.\n",edge);for(i=1;i<=edge;i++){scanf("%d%d%d",&x,&y,&data);G->matrix[x][y].info=data;G->matrix[y][x].info=data;}}//找出给定顶点的位置int LocateVex(Graph *G,int V){int i;for(i=1;i<=G->vertex;i++)if(G->vexs[i] == V)return i;return -1;//失败返回-1}void RecoverGraph(Graph *G){int i,k;for(i=1;i<=G->vertex;i++)for(k=1;k<=G->vertex;k++)G->matrix[i][k].info=0;memset(G->vexs,0,sizeof(G->vexs));G->vertex = G->edge = 0;}//查找当前弧是否构成环路,这里要用到并查集。//这一步很关键,防止多余的边。 int Find(int digit[],int k){while(digit[k] > 0)k = digit[k];return k;}void Kruskal(Graph *G){Edge node[number];int AlreadyFind[number];//存储已经找到的弧int i,k,count=0,m,n;int sum=0;//初始化for(i=0;i<=G->vertex;i++)AlreadyFind[i]=0;//查找所有的弧for(i=1;i<=G->vertex;i++){for(k=i+1;k<=G->vertex;k++)if(G->matrix[i][k].info < MAX){node[count].info = G->matrix[i][k].info;node[count].begin = i;node[count].end = k;count++;}}//对弧的权值进行排序。。这里偷懒一下qsort(node,count,sizeof(Edge),cmp);for(i=0;i<count;i++){n = Find(AlreadyFind,node[i].begin);m = Find(AlreadyFind,node[i].end);//如果所找的弧不构成回路,就添加到AlreadyFind数组中if(m!=n){AlreadyFind[n]=m;printf("%d---%d\n",node[i].begin,node[i].end);//按照顺序输出弧}}}int main(){Graph G;CreatGraph(&G);Kruskal(&G);RecoverGraph(&G);return 0;}/************************************************************************//*    //顶点个数和弧的个数6 10//顶点1 2 3 4 5 6//弧1 2 6 2 5 3 5 6 6 6 4 2 4 1 5 1 3 1 2 3 5 5 3 6 6 3 4 4 3 5*//************************************************************************/