求最小生成树 C语言描述

原帖地址:http://blog.163.com/zhoumhan_0351/blog/static/39954227200972732436582/

克鲁斯卡尔算法:

算法构造一棵最小生成树的过程如下:


算法的描述:

在图中任取一个顶点K作为开始点,令U={k},W=V-U,其中V为图中所有顶点集,然后找一个顶点在U中,另一个顶点在W中的边中最短的一条,找到后,将该边作为最小生成树的树边保存起来,并将该边顶点全部加入U集合中,并从W中删去这些顶点,然后重新调整U中顶点到W中顶点的距离, 使之保持最小,再重复此过程,直到W为空集止。

假设G=(V,E)是一个具有n个顶点的带权无向连通图,T= (U,TE)是G的最小生成树,其中U是T的顶点集,TE是T的边集,则构造最小生成树的过程如下:

(1) 置U的初值等于V,TE的初值为空集;

(2) 按权值从小到大的顺序依次选取图G中的边,若选取的边未使生成树T形成回路,则加入TE;若选取的边使生成树T形成回路,则将其舍弃。循环执行(2),直到TE中包含(n-1)条边为止。

完整代码:

#include "stdio.h"
#define MAXE 11                   //最大边数
#define MAXV 10                   //最大顶点数
typedef struct
{
	int vex1;                     //边的起始顶点
	int vex2;                      //边的终止顶点
	int weight;                    //边的权值
}edge;                       
void kruskal(edge E[], int n, int e)
{
	int i, j, m1, m2, sn1, sn2, k;
	int vset[MAXV];
	for (i = 1; i <= n; i++)        //初始化辅助数组
		vset[i] = i;
	k = 1;        //表示当前构造最小生成树的第k条边,初值为1
	j = 0;                   //E中边的下标,初值为0
	while (k < e)            //生成的边数小于e时继续循环
	{
		m1 = E[j].vex1;
		m2 = E[j].vex2;//取一条边的两个邻接点
		sn1 = vset[m1];
		sn2 = vset[m2];//分别得到两个顶点所属的集合编号
		if (sn1 != sn2)
			//两顶点分属于不同的集合,该边是最小生成树的一条边
		{
			printf("(v%d,v%d): %d\n", m1, m2, E[j].weight);
			k++;                //生成边数增l
			if (k >= n)  break;
			for (i = 1; i <= n; i++)    //两个集合统一编号
				if (vset[i] == sn2)  //集合编号为sn2的改为sn1
					vset[i] = sn1;
		}//if
		j++;                  //扫描下一条边
	}//while
}//kruskal
int main()
{
	edge E[MAXE];
	int nume, numn;
// 	printf("输入边数和顶点数','分隔:\n");
// 	scanf("%d,%d",&nume,&numn);
	nume = 10;
	numn = 6;
// 	printf("请输入各边及对应的的权值(起始顶点 终止顶点 权值)\n");
// 	for(int i=0;i
   
   
普里姆算法:
算法构造一棵最小生成树的过程如下:

算法描述:

从连通网络 N = { V, E }中的某一顶点 u0 出发,选择与它关联的具有最小权值的边(u0, v),将其顶点加入到生成树的顶点集合U中。以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u, v),把该边加入到生成树的边集TE中,把它的顶点加入到集合U中。如此重复执行,直到网络中的所有顶点都加入到生成树顶点集合U中为止。

假设G=(VE)是一个具有n个顶点的带权无向连通图,T(UTE)G的最小生成树,其中UT的顶点集,TET的边集,则构造G的最小生成树T的步骤如下:

  1)初始状态,TE为空,U={v0}v0V

  2)在所有uUvV-U的边(uv) E中找一条代价最小的边(u′,v)并入TE,同时将v′并入U

 重复执行步骤(2n-1次,直到U=V为止。

        在普里姆算法中,为了便于在集合U(V-U)之间选取权值最小的边,需要设置两个辅助数组closestlowcost,分别用于存放顶点的序号和边的权值。
       
对于每一个顶点vV-Uclosest[v]U中距离v最近的一个邻接点,即边(vclosest[v]) 是在所有与顶点v相邻、且其另一顶点jU的边中具有最小权值的边,其最小权值为lowcost[v],即lowcost[v]=cost[v][closest[v]],采用邻接表作为存储结构:

设置一个辅助数组closedge[]

 lowcost   存放生成树顶点集合内顶点到生成树外各顶点的各边上的当前最小权值;

adjvex  记录生成树顶点集合外各顶点距离集合内哪个顶点最近(即权值最小) 

完整代码:
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include "string.h"
#define INFINITY 65535
typedef int status;
#define maxlen 10
typedef struct
{
	char vexs[maxlen][maxlen];/*顶点信息集合,我们用它来存入顶点名字*/
	int vexnum, arcnum;/*顶点数和边数*/
	int arcs[maxlen][maxlen];/*邻接矩阵*/
}graph;
//定位输入节点的名称
int LocateVex(graph G, char u[maxlen])
{
	int i;
	for (i = 0; i
        
        
       
       
      
      
     
     



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值