数据结构——Prim算法

Prim算法(加点法)

  • Prim为求图最小生成树的算法
  • 本文章采用邻接矩阵的存储方式

具体思路如下

  • 1.首先以邻接矩阵方式输入图
  • 2.进入算法函数
  • 3.设置closedge数组辅助
  • 4.先将一个start顶点加入生成树顶点集合中
  • 5.用start顶点的边关系将closedge数组初始化
  • 6.找出当前closedge没有进入生成树的顶点中lowcost最小值记为min,对应的顶点记为m
  • 7.将m顶点加入到生成树顶点集合中
  • 8.打印刚加入的顶点与权值最小边的信息
  • 9.用m顶点的信息更新closedge数组的信息,如果发现更小的权值边出现,则替换原有信息
  • 10.重复6-9直到找出n-1条边是结束

具体代码如下

/*prim算法(加点法),适合稠密图*/

#include<stdio.h>
#include<stdlib.h>

#define MAXVEX      20             /*最大顶点个数*/ 
#define INFINITY    32767          /*表示无穷,可自定义*/

#define Elem        int
#define FALSE       0
#define OK          1
#define TRUE        1

typedef char VertexType;

typedef struct{
	int arcs[MAXVEX][MAXVEX];            //邻接矩阵,边的信息
	VertexType vexs[MAXVEX];        //顶点信息 
	int vexnum;      //顶点数目 
	int arcnum;      //边(弧)数目 
	
}AdjMatrix; 

typedef struct{    //数组元素的下标对应图G的顶点序号 
	int adjvex;   /*记录该顶点和顶点集合中相连权值最小的顶点序号*/
	int lowcost;  /*记录最小的权值*/ 
}Closedge;   

//根据名称得到指定顶点在顶点集合中的下标
int getIndexOfVexs(char vex,AdjMatrix *MG)
{
	for(int i=1;i<=MG->vexnum;i++)
	{
		if(MG->vexs[i]==vex) return i;
	}
	return 0;
}

//用邻接矩阵创建图 
void Create(AdjMatrix *MG){
	int v1,v2;
	char c1,c2;

	printf("请输入顶点数目: ");         //输入顶点数 
	scanf("%d",&MG->vexnum);
	printf("请输入边的数目: ");         //输入边数 
	scanf("%d",&MG->arcnum);
	getchar();
	
    //输入各顶点信息 
	for(int i=1;i<=MG->vexnum;i++)
	{
		printf("请输入第%d个顶点(char): ",i);    //请输入各顶点信息   
		scanf("%c",&MG->vexs[i]);
		getchar();
	}
	
	//初始化邻接矩阵
	for(int i=1;i<=MG->vexnum;i++)
		for (int j=1;j<=MG->vexnum;j++)
			MG->arcs[i][j]=INFINITY;               /*如果是网则赋值INFINITY */ 
			
	//输入边的信息,建立邻接矩阵
	for(int k=1;k<=MG->arcnum;k++)
	{
		printf("请输入第%d个边连接的两个顶点及权值v1(char) v2(char) weight(int): ",k);  //请输入有关系的两个顶点 
		int weight=INFINITY;
		scanf("%c %c %d",&c1,&c2,&weight);
		v1=getIndexOfVexs(c1,MG);
		v2=getIndexOfVexs(c2,MG);
		MG->arcs[v1][v2]=weight; 
		MG->arcs[v2][v1]=weight;   //无向图为对称矩阵
		getchar();
	}
}

//打印图的信息 
void Printf(AdjMatrix MG)
{
	printf("顶点数目为: %d\n",MG.vexnum);
	printf("边的数目为: %d\n",MG.arcnum);
	printf("顶点: ");
	for(int i=1;i<=MG.vexnum;i++)
		printf("%c",MG.vexs[i]);
		
	printf("\n邻接矩阵为: \n");
	for(int i=1;i<=MG.vexnum;i++)
	{
		for(int j=1;j<=MG.vexnum;j++){
			if(MG.arcs[i][j]==INFINITY) printf("#");
			else printf("%d",MG.arcs[i][j]);
		}
			
		printf("\n");
	}
}

/****************最小生成树(Prim算法)***************/ 
void Prim(AdjMatrix G,int start){
	Closedge closedge[MAXVEX];
	
	closedge[start].lowcost=0;  /*标志顶点加入到生成树集合中*/
	
	//初始化剩下的所有顶点对应的closedge数组
	for(int i=1;i<=G.vexnum;i++){
		if(i!=start){
			closedge[i].adjvex=start;
			closedge[i].lowcost=G.arcs[start][i];
		}
	} 
	printf("\n最小生成树的生成过程:"); 
	//从边集中选出n-1条符合条件的边 
	for(int e=1;e<=G.vexnum-1;e++){
		int m;             //记录顶点 
		int min=INFINITY;  //记录最小权值 
		//找出当前closedge没有进入生成树的顶点中lowcost最小值对应的顶点
		for(int k=1;k<=G.vexnum;k++){       
			if((closedge[k].lowcost!=0)&&closedge[k].lowcost<min){
				min=closedge[k].lowcost;
				m=k;
			}
		}
		
		printf("\n(%c,%c)  %d",G.vexs[closedge[m].adjvex],G.vexs[m],min);
		closedge[m].lowcost=0;     /*标志顶点m进入生成树集合*/
		
		//用新的生成树顶点m,更新closedge数组
		for(int i=1;i<=G.vexnum;i++){
			if((closedge[i].lowcost!=0)&&G.arcs[m][i]<closedge[i].lowcost){
				//如果发现有更小的权值边出现,则替换原有信息
				closedge[i].lowcost=G.arcs[m][i];
				closedge[i].adjvex=m; 
			}
		} 
	} 
} 


int main(){
	AdjMatrix MG,T;
	Create(&MG); 
	Prim(MG,1);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41596568/article/details/84640994