关闭

Kruskal算法实现

标签: 并查集优先队列Kruskal算法
175人阅读 评论(0) 收藏 举报
分类:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <queue>
#define NUM 6
#define MAXSIZE 30
using namespace std;

//定义并查集树
typedef struct UNode
{
     int data;
     int rank;
     int parent;
} UNode,UFSTree;

//定义邻接矩阵
typedef struct Node
{
     int num;
     int data;
} Node;
typedef struct MGraph
{
     int edges[NUM][NUM];
     int n,e;
} MGraph;

//定义边
typedef struct Edge
{
     int u;//起点
     int v;//终点
     int w;//权值

     bool operator < (const Edge &a) const
     {
	  return w > a.w;
     }
} Edge;

MGraph *build_graph();
void kruskal(MGraph *mgraph);
void MAKE_SET(UFSTree t[], int n);
int FIND_SET(UFSTree t[], int x);
void UNION(UFSTree t[], int x, int y);

int main(void )
{
     MGraph *mgraph;

     mgraph=build_graph();
     kruskal(mgraph);
     return 0;
}

MGraph *build_graph()
{
     MGraph *mgraph;
     int i,j;
     int this_edges=0;
     int arrays[NUM][NUM]={{0,6,1,5,INT_MAX,INT_MAX},
			   {6,0,5,INT_MAX,3,INT_MAX},
			   {1,5,0,5,6,4},
			   {5,INT_MAX,5,0,INT_MAX,2},
			   {INT_MAX,3,6,INT_MAX,0,6},
			   {INT_MAX,INT_MAX,4,2,6,0}};
     mgraph=(MGraph *)malloc(sizeof(MGraph));
     for(i=0;i<NUM;i++)
     {
	  for(j=0;j<NUM;j++)
	  {
	       mgraph->edges[i][j]=arrays[i][j];
	       if(arrays[i][j]!=0 && arrays[i][j]!=INT_MAX)
	       {
		    this_edges++;
	       }
	  }
     }
     mgraph->n=NUM;
     mgraph->e=this_edges;

     //测试生成的邻接矩阵
     printf("node=%d,edges=%d\n",mgraph->n,mgraph->e);
     for(i=0;i<NUM;i++)
     {
	  for(j=0;j<NUM;j++)
	  {
	       if(mgraph->edges[i][j]!=INT_MAX)
	       {
		    printf("%3d",mgraph->edges[i][j]);
	       }
	       else
	       {
		    printf("%3c",'&');
	       }
	  }
	  printf("\n");
     }
     
     return mgraph;
}

//Kruskal算法
void kruskal(MGraph *mgraph)
{
     int i,j;
     int k;			// 存储已并入的边数
     int u1,v1;			// 存储当前最小边
     int sn1,sn2;		// 存储两个顶点所属集合
     UFSTree t[MAXSIZE];	// 存储并查集树
     Edge E[MAXSIZE];		// 存储所有的边
     priority_queue<Edge> pq;	// 优先队列,每次弹出最小边

     //把所有边存入优先队列
     k=1;
     for(i=0;i<mgraph->n;i++)
     {
	  for(j=0;j<=i;j++)
	  {
	       if(mgraph->edges[i][j]!=0 && mgraph->edges[i][j]!=INT_MAX)
	       {
		    E[k].u=i;
		    E[k].v=j;
		    E[k].w=mgraph->edges[i][j];
		    pq.push(E[k]);
	       }
	  }
     }

     MAKE_SET(t,mgraph->n);	// 初始化并查集

     //每次选出最小边并入
     k=1;
     while(k<mgraph->n)
     {
	  u1=pq.top().u;
	  v1=pq.top().v;

	  sn1=FIND_SET(t,u1);
	  sn2=FIND_SET(t,v1);
	  if(sn1!=sn2)
	  {
	       printf("%d-%d: %d\n",u1,v1,pq.top().w);
	       k++;
	       UNION(t,u1,v1);
	  }
	  pq.pop();
     }
     
}

//初始化并查集
void MAKE_SET(UFSTree t[], int n)
{
     int i;
     for(i=0;i<n;i++)
     {
	  t[i].data=i;
	  t[i].rank=0;
	  t[i].parent=i;
     }
}
//并查集查找
int FIND_SET(UFSTree t[], int x)
{
     if(x!=t[x].parent)
	  return FIND_SET(t,t[x].parent);
     else
	  return x;
}
//并查集合并
void UNION(UFSTree t[], int x, int y)
{
     x=FIND_SET(t,x);
     y=FIND_SET(t,y);

     if(t[x].rank > t[y].rank)
	  t[y].parent=x;
     else
     {
	  t[x].parent=y;
	  if(t[x].parent==t[y].parent)
	       t[y].rank++;
     }
}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:15633次
    • 积分:1057
    • 等级:
    • 排名:千里之外
    • 原创:93篇
    • 转载:1篇
    • 译文:1篇
    • 评论:1条
    最新评论