最小生成树Prim和Kruskal算法

采用邻接矩阵的存储结构构建无向网,然后用Prim和Kruskal算法求出最小生成树。

总代码:

#include <stdio.h>
#include <stdlib.h>
#define VRType int//在这里是权值类型
#define MAX_VERTEX_NUM 10//最大顶点个数
#define VertexType char //顶点类型
#define INFINITY 32767 //无穷大,不连通
//边的结构
typedef struct ArcCell{
	VRType adj;//权值
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
//图的结构
typedef struct {
	VertexType vexs[MAX_VERTEX_NUM];//顶点向量
	AdjMatrix arcs;//邻接矩阵
	int vexnum,arcnum;//顶点数,边数
}MGraph;
//辅助数组,记录从U到V-U的最小代价的边
typedef struct {
	VertexType adjvex;
	VRType lowcost;
}Closedge;
//
typedef struct edge{
	int begin;//起始顶点位置
	int end;//终点位置
	VRType weight;//权重
}Edge[100];

//函数声明
void CreateMGraph(MGraph &G);
void Prim(MGraph G,VertexType v);
void Kruskal(MGraph G);
int LocateVex(MGraph G,VertexType v);

int main(){
	int i=1;
	MGraph G;
	VertexType v;
	while(i){
		printf("第%d个图:\n",i++);
		CreateMGraph(G);
		//Prim算法
		printf("========Prim算法========:\n输入从哪个顶点开始构造:");
		fflush(stdin);
		scanf("%c",&v);
		Prim(G,v);
		//Kruskal算法
		printf("\n========Kruskal算法========:\n");
		Kruskal(G);
		system("pause");
	}
	return 0;
}
//函数实现
int minimum(Closedge *closedge,MGraph G){
	int i=0,j,k,min;
	while(!closedge[i].lowcost){//找到第一个权值不为零的
		i++;
	}
	min = closedge[i].lowcost;
	k = i;
	for(j=i+1;j<G.vexnum;j++){
		if(closedge[j].lowcost >0 && min >closedge[j].lowcost){
			min = closedge[j].lowcost;
			k = j;
		}
	}
	return k;
}
void Prim(MGraph G,VertexType v){
	int k = LocateVex(G,v),i=0,j=0;
	Closedge closedge[MAX_VERTEX_NUM];
	//辅助矩阵初始化
	for(i=0;i<G.vexnum;i++){
			closedge[i].adjvex = v;
			closedge[i].lowcost = G.arcs[k][i].adj;
//			printf("==%d\n",closedge[i].lowcost);
	}
	closedge[k].lowcost = 0;//把结点v加入集合U中
	for(i=1;i<G.vexnum;i++){
		k = minimum(closedge,G) ;//求出最小生成树的下一个节点,第k顶点
		printf("%c--->%c\n",closedge[k].adjvex,G.vexs[k]);
		closedge[k].lowcost = 0;//第k结点加入U
		//重新选择最小边
		for(j=0;j<G.vexnum;j++){
			if( G.arcs[k][j].adj < closedge[j].lowcost){
				closedge[j].adjvex = G.vexs[k];
				closedge[j].lowcost = G.arcs[k][j].adj;
			}
		}
	}
}
//打印边数组
void print(Edge *E,int n,MGraph G){
	for(int i=0;i<n;i++){
		printf("%c---%c---%d\n",G.vexs[E[i]->begin],G.vexs[E[i]->end],G.arcs[E[i]->begin][E[i]->end].adj);
	}
}
//按权值从小到大排序
int cmp(const void *a,const void *b){
	return ((struct edge*)a)->weight - ((struct edge*)b)->weight;
}
void Kruskal(MGraph G){
	Edge *E = (Edge*)malloc(sizeof(Edge)*G.arcnum*2) ;
	int i=0,j=0,k=0;
	for(i=0;i<G.vexnum;i++){
		for(j=0;j<G.vexnum;j++){
			if(G.arcs[i][j].adj != INFINITY){
				E[k]->begin = i;
				E[k]->end = j;
				E[k]->weight = G.arcs[i][j].adj;
				k++;
			}
		}
	}
	qsort(E,k,sizeof(E[0]),cmp);
	print(E,k,G);
	int *vset = (int *)malloc(sizeof(int)*G.vexnum);
	for (i=0;i<G.vexnum;i++){                                  //初始化辅助数组    
        vset[i]=i;  
    }  
    k=1;                                                   //生成的边数,最后要刚好为总边数   
    j=0;                                                   //E中的下标   
    while (k<G.vexnum){   
        int set1 = vset[E[j]->begin];  
        int set2 = vset[E[j]->end];                                  //得到两顶点属于的集合   
        if (set1!=set2){                                    //不在同一集合内的话,把边加入最小生成树   
			printf("%c--->%c weight = %d\n",G.vexs[E[j]->begin],G.vexs[E[j]->end],E[j]->weight);
            k++;  
            for (i=0;i<G.vexnum;i++)  
            {  
                if (vset[i]==set2)  
                {  
                    vset[i]=set1; //避免重复添加,像A-B添加后B-A又添加
                }  
            }             
        }  
        j++;  
    }  
	free(vset);
	free(E);
}
void CreateMGraph(MGraph &G){
	printf("输入顶点数,边数:");
	scanf("%d %d",&G.vexnum,&G.arcnum);
	int i=0,j=0;
	for(i=0;i<G.vexnum;i++){
		printf("输入第%d个顶点编号:",i+1);
		fflush(stdin);
		scanf("%c",&G.vexs[i]);
	}
	//初始化矩阵
	for(i=0;i<G.vexnum;i++){
		for(j=0;j<G.vexnum;j++){
			G.arcs[i][j].adj = INFINITY;
		}
	}
	char v1,v2;
	int w;
	for(int k=0;k<G.arcnum;k++){
		printf("输入顶点1,顶点2及其权值:");
		fflush(stdin);
		scanf("%c %c %d",&v1,&v2,&w);
		i = LocateVex(G,v1);
		j = LocateVex(G,v2);
		G.arcs[i][j].adj = w;
		G.arcs[j][i] = G.arcs[i][j];//对称边
//		printf("%d\n",G.arcs[j][i].adj);
	}
}
int LocateVex(MGraph G,VertexType v){
	for(int i=0;i<G.vexnum;i++){
		if(v == G.vexs[i]){
			return i;
		}
	}
	return -1;
}


运行结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值