c语言实现普利姆算法

c语言实现普利姆算法

以王卓老师讲的思路编写的c语言版的普利姆算法

如图,先构建一个图G,输入顶点数,边数,边的名字,这里我用a~f来命名,再输入边的权值,先输入边的两个顶点,再输入对应的权值,在将所有的边输入完毕后,就构建好了图G,下面会输出图G的邻接矩阵和图G的最小生成树的邻接矩阵,注意调用构建最小生成树函数的时候要指明从哪个结点开始。 作者:Wanna_雄 https://www.bilibili.com/read/cv16003601 出处:bilibili
下面示例使用的图G
在这里插入图片描述

1.构建图G,分别输入结点数,边数,结点名称,权值。
s在这里插入图片描述

2.图的邻接矩阵
在这里插入图片描述
3.生成树的邻接矩阵
在这里插入图片描述

代码

#include<stdio.h> 
#include<string.h>
#include<stdlib.h>
#define maxsize 100
typedef char vertextype;		//定义结点类型 
typedef int arctype;			//定义边类型 

typedef struct{			//定义邻接矩阵的结构体 
	vertextype vexs[maxsize];
	arctype arcs[maxsize][maxsize];
	int vexnum,arcnum;
}Amgraph;

typedef struct{		//定义最小生成树的结构体 
	int vexnum1;
	int arcnum1;
	int TE[maxsize][maxsize];
}LTgraph; 

int locatevex(Amgraph G,char v){		//返回结点v的数组下标 
	int m=0;
	for(m=0;m<G.vexnum && G.vexs[m]!=v;m++);
	printf("the location is %d\n",m);
	return m;
}
	
void creatudn(Amgraph &G){		//创建图,初始化图 
	for(int i=0;i<maxsize;i++){		//初始化邻接矩阵全为0; 
		for(int j=0;j<maxsize;j++){
			G.arcs[i][j]=0;
		}
	}
	printf("please enter the vexnum:");		//输入结点数 
	scanf("%d",&G.vexnum);
	printf("\n");
	printf("please enter the arcnum:");		//输入边数 
	scanf("%d",&G.arcnum);
	printf("\n");
	for(int i=0;i<G.vexnum;i++){			//输入结点名称 
		printf("please enten the %d's vex",i);
		scanf("%s",&G.vexs[i]);
		printf("\n");
	}
	for(int i=0;i<G.vexnum;i++){
		for(int j=0;j<G.vexnum;j++){
			G.arcs[i][j]=0;
		}
	}
	
	for(int k=0;k<G.arcnum;k++){		//输入权值,格式为(V1,V2,Weight) ; 
		char v1;
		char v2;
		int w;
		printf("please enter vex1:");
		char c=getchar();
		scanf("%c",&v1);
		printf("the v1 is %c\n",v1);
		printf("please enter vex2:");
		char d=getchar();
		scanf("%c",&v2);
		printf("the v2 is %c\n",v2);
		printf("\n");
		printf("please enter the weight:");
		scanf("%d",&w);
		printf("\n");
		int i = locatevex(G,v1);
		//printf("%d",i);
		int j = locatevex(G,v2);
		//printf("%d",j);
		G.arcs[i][j] = w;
		G.arcs[j][i] = G.arcs[i][j];
		//printf()
	}
}

void DFS(Amgraph G,int v,int visit[ ]){		//深度优先遍历图 
	printf("%c\t",G.vexs[v]);
	//int visit[G.vexnum];
	visit[v]=1;
	int w=0;
	for(w=0;w<G.vexnum;w++){
		if(G.arcs[v][w]!=0 && visit[w]!=1){
			DFS(G,w,visit);
		}
	}
}

void WFS(Amgraph G,int v,int visit[ ],int lun[ ]){		//广度优先遍历图 
	if(visit[v]!=1){
		printf("%c\t",G.vexs[v]);
		visit[v]=1;
	}
	//printf("%c",G.vexs[v]);
	for(int w=0;w<G.vexnum;w++){
		if(G.arcs[v][w]!=0 && visit[w]!=1){
			printf("%c\t",G.vexs[w]);
			visit[w]=1;
		}
	}
	lun[v]=1;
	for(int w=0;w<G.vexnum;w++){
		if(G.arcs[v][w]!=0  && lun[w]!=1){
			WFS(G,w,visit,lun);
		}
	}
}

int findleastarc(LTgraph &LT,Amgraph G,int u[ ],int v[ ]){
	//printf("has in the find") ;
	int w=0,m=0;		//用于记录找到最小权值时的数组下标 
	int least=maxsize;	//暂存最小权值 
	for(int i=0;i<LT.vexnum1;i++){		//遍历图G的邻接矩阵,在u集合上的点的邻接点中权值最小的,加入集合u中,把边加入TE矩阵中 
		if(u[i]==1){
			for(int j=0;j<LT.vexnum1;j++){
				if(G.arcs[i][j]!=0 && u[j]==0){
					if(G.arcs[i][j]<least){
						least=G.arcs[i][j];
						w=j;
						m=i; 
					}
				}
			}
		}
	}
	LT.TE[m][w]=G.arcs[m][w];		//TE为一邻接矩阵 用来表示最小生成树,这里w和m表示找到的权值最小的边的尾结点的下标 
	LT.TE[w][m]=LT.TE[m][w];		
	u[w]=1;							//对U和V进行修改,来达到增加和删除的操作 
	v[w]=0;
	int i=0;
	for(i=0;i<LT.vexnum1 && u[i]==1;i++);	//查看U中是否包含所有的结点 
	if(i<LT.vexnum1){
		printf("i=%d\n",i);
		findleastarc(LT,G,u,v);
	}
	return 1;
}

void prime(Amgraph G,LTgraph &LT,int v){	//普利姆算法构建最小生成树 
//	printf("has in");
	int U[G.vexnum];		//定义数组u来存放已经找到的结点 
	int V[G.vexnum];		//v来存储u之外的结点 
	for(int i=0;i<LT.arcnum1;i++){		//初始化,用TE来表示最小生成树的邻接矩阵 
		for(int j=0;j<LT.arcnum1;j++){
			LT.TE[i][j]=0;
		}
	}
	for(int i=0;i<LT.vexnum1;i++){	//初始化u,V数组 
		U[i]=0;
		V[i]=1;
	}
	U[v]=1;
	V[v]=0;
	printf("has in");
	findleastarc(LT,G,U,V);
		/*普利姆算法过程,从v结点开始,置结点U【v】 为1,V【v】 为0,
		查找U 数组上为1的节点,即已经找过的节点,遍历这些结点的邻接点,
		找到其中权值最小的边,将边尾结点加入U数组中,v数组剔除掉他,再递归调用该函数,直到u数组中包含所有的结点 
		*/ 
}



int main(){
	Amgraph G;	//定义图G
	LTgraph LT; 	//定义生成树LT
	creatudn(G);	//构建图G
	LT.vexnum1 = G.vexnum;	//生成树的结点数=图的结点数
	LT.arcnum1=LT.vexnum1-1;
	for(int i=0;i<G.vexnum;i++) {	//输出图G的邻接矩阵
		for(int j=0;j<G.vexnum;j++){
			printf("%d  ",G.arcs[i][j]);
		}
		printf("\n");
	}
	printf("\n");
	prime(G,LT,0);	//普利姆算法构建最小生成树
	//printf("prime has done");
	int visit[G.vexnum];	//这个时深度广度遍历中记录结点是否被遍历过的数组
	int visit1[G.vexnum];
	int lun[G.vexnum];	
	for(int i=0;i<G.vexnum;i++) {	//输出最小生成树的邻接矩阵
		for(int j=0;j<G.vexnum;j++){
			printf("%d  ",LT.TE[i][j]);
		}
		printf("\n");
	}
	//DFS(G,0,visit);
	//printf("\n");
	//WFS(G,0,visit1,lun);
	return 0;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值