构造最小生成树——Kruskal算法

算法描述:

找到权最小的一条边,加入生成树;

再在剩下的边中找到权最小的边加入生成树;

但是不能形成回路。


代码:


<span style="font-family:Microsoft YaHei;">#include <stdio.h>

#define MAXVEX 9
#define MAXEDGE 15
#define INFINITY 65535

typedef int EdgeType;

//对边集数组Edge结构的定义
typedef struct
{
	int begin;
	int end;
	int weight;
}Edge;

//邻接矩阵结构
typedef struct 
{
	EdgeType arc[MAXVEX][MAXVEX];
	int numVertexes,numEdge;	//当前图中的顶点数和边数
}MGraph;

void CreateMGraph(MGraph *G)
{
	int i,j;

	G->numVertexes = 9;
	G->numEdge = 15;

	//初始化图
	for(i=0;i<G->numVertexes;i++)    
        for(j=0;j<G->numVertexes;j++)    
        {  
            if(i==j)  
                G->arc[i][j] = 0;    
            else  
                G->arc[i][j] =INFINITY;  
        }  
    
    G->arc[0][1]=10;    
    G->arc[0][5]=11;    
    
    G->arc[1][2]=18;    
    G->arc[1][6]=16;    
    G->arc[1][8]=12;    
    
    G->arc[2][3]=22;    
    G->arc[2][8]=8;    
    
    G->arc[3][4]=20;      
	G->arc[3][6]=24;
	G->arc[3][7]=16; 
    G->arc[3][8]=21;    
    
    G->arc[4][5]=26;    
    G->arc[4][7]=7;    
    
    G->arc[5][6]=17;    
    
    G->arc[6][7]=19;    
    
    //对称矩阵    
    for(i=0;i<G->numVertexes;i++)    
        for(j=i;j<G->numVertexes;j++)    
            G->arc[j][i] = G->arc[i][j];   

}

//交换头、尾和权值,用于交换排序
void Swap(Edge *edge,int i,int j)
{
	int temp;
	EdgeType temp_weight;

	temp = edge[i].begin;
	edge[i].begin = edge[j].begin;
	edge[j].begin = temp;

	temp = edge[i].end;
	edge[i].end = edge[j].end;
	edge[j].end = temp;

	temp_weight = edge[i].weight;
	edge[i].weight = edge[j].weight;
	edge[j].weight = temp_weight;
}


//对权值进行排序
void sort(Edge edges[],MGraph *G)
{
	int i,j;
	for(i=0;i<G->numEdge;i++)
	{
		for(j=i+1;j<G->numEdge;j++)
		{
			if(edges[i].weight > edges[j].weight)
				Swap(edges,i,j);
		}
	}
	printf("权值排序后为:\n");
	for(i=0;i<G->numEdge;i++)
		printf("(%d,%d) %d\n",edges[i].begin,edges[i].end,edges[i].weight);
}


//查找连接顶点的尾部下标
int Find(int *parent,int f)
{
	while(parent[f]>0)
	{
		f=parent[f];
	}
}

//Kruskal算法生成最小生成树
void MiniSpanTree_Kruskal(MGraph G)
{
	int i,j,n,m;
	int k=0;
	Edge edges[MAXEDGE];		//定义边集数组
	int parent[MAXVEX];		//定义parent数组用来判断边与边是否形成环路

	//用来构建边集数组并排序
	for(i=0;i<G.numVertexes-1;i++)
	{
		for(j=i+1;j<G.numVertexes;j++)
		{
			if(G.arc[i][j]<INFINITY)
			{
				edges[k].begin =i;
				edges[k].end = j;
				edges[k].weight = G.arc[i][j];
				k++;
			}
		}
	}
	sort(edges,&G);

	for(i=0;i<G.numVertexes;i++)
	{
		parent[i]=0;
	}

	for(i=0;i<G.numVertexes;i++)
	{
		n = Find(parent,edges[i].begin);
		m = Find(parent,edges[i].end);

		if(n!=m)			//如果n=m,则形成环路,不满足
		{
			parent[n]=m;	//将此边的结尾顶点放入下标为起点的parent数组中,表示此顶点已经在生成树中
			printf("(%d,%d) %d ",edges[i].begin,edges[i].end,edges[i].weight);
		}
	}
}

int main()
{
	MGraph G;
	CreateMGraph(&G);
	MiniSpanTree_Kruskal(G);

	return 0;
}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值