贪心策略-最小生成树Prim算法

#include <stdio.h>
#include <stdlib.h>
#define PeakMax 20 //最大顶点数为20
#define MaxInt 32767 //表示 ∞ 

typedef char PeakType; 

typedef struct//邻接矩阵结构体 
{
	PeakType Peak[PeakMax];//顶点元素
	int ADJ[PeakMax][PeakMax];//邻接矩阵 
	int peaknum,sidenum;//图的顶点和边的数目 
}MG;

typedef struct//辅助数组结构体(候选最短边) 
{
	PeakType adjpeak;//最短边的邻接点 
	int lowcost;//最短边的权值 
}ShortEdge;

int LocatMark(MG *G,PeakType v)//查找元素v的下标,并返回下标 
{
	int i;
	
	for(i=0;i<G->peaknum;i++)
	{
		if(v==G->Peak[i])
		{
			return i; 
		} 
	 } 
	 
	 printf("没有此顶点!\n");
	 return -1;
}

void CreateUndig(MG *G)//构建无向网
{
	int i,j;
	
	printf("请输入顶点个数和边条数:\n");
	printf("顶点数为:"); 
	scanf("%d",&G->peaknum);
	printf("边  数为:"); 
	scanf("%d",&G->sidenum);
	printf("\n"); 
	
	printf("\n");
	
	
	printf("请输入顶点名称(不用空格隔开):");
	scanf("%s",G->Peak);
	printf("\n");
	
	for(i=0;i<G->peaknum;i++) 
	 for(j=0;j<G->peaknum;j++)
	    {
	    	G->ADJ[i][j]=MaxInt;
		}
	
	 
	 int n,m;
	 PeakType v1,v2;
	 int w; 
	 
	 printf("请输入边的名称和权值(例:AB,15):\n");
	 for(i=0;i<G->sidenum;i++)
	 {
	 	printf("输入第%d条边名称和权值:",i+1);
	 	scanf(" %c%c,%d",&v1,&v2,&w);
	 	n=LocatMark(G,v1); 
	 	m=LocatMark(G,v2); 
	 	
	 	if(n==-1||m==-1)
		 {
		 	printf("没有此顶点!\n");
		 	return;
		  } 
	
	   G->ADJ[n][m]=w;
	   G->ADJ[m][n]=w; 
     } 
}

void PrintADJ(MG G)
{
	int i,j;
	printf("\n-------------------------------");
	printf("\n 邻接矩阵如下:\n\n"); 	
	
		printf("\t ");
		for(i=0;i<G.peaknum;i++)
		printf("\t%c",G.Peak[i]);
		printf("\n");
		 
		for(i=0;i<G.peaknum;i++)
	   {
	   	  printf("\t%c",G.Peak[i]);
	   	  
		  for(j=0;j<G.peaknum;j++)
	    {
	    	
	    	if(G.ADJ[i][j]==MaxInt)
	 	    printf("\t∞");
	 	    else printf("\t%d",G.ADJ[i][j]);
	    }
	      printf("\n");
	   }

	 
}

int minimal(MG *G,ShortEdge *shortedge)
{
	int i,j;
	int min,loc;
	
	min=MaxInt;
	for(i=1;i<G->peaknum;i++)
	{
		if(min>shortedge[i].lowcost&&shortedge[i].lowcost!=0)
		{
			min=shortedge[i].lowcost;
			loc=i;
		}
	}
	return loc;
}
 
void MiniSpanTree_Prim(MG *G,PeakType start)
{ 
	int i,j,k;
	ShortEdge shortedge[PeakMax];
	
	 
	k=LocatMark(G,start);
	for(i=0;i<G->peaknum;i++)
	{
		shortedge[i].adjpeak=start;
		shortedge[i].lowcost=G->ADJ[k][i];
	}
	shortedge[k].lowcost=0;
	
	 
	for(i=0;i<G->peaknum-1;i++) 
	{
		k=minimal(G,shortedge);
	
	    printf("%c->%c,%d\n",shortedge[k].adjpeak,G->Peak[k],shortedge[k].lowcost); 
	    shortedge[k].lowcost=0;
	    
	    for(j=0;j<G->peaknum;j++) 
	    {
	    	if(G->ADJ[k][j]<shortedge[j].lowcost)
	    	{
	    		shortedge[j].lowcost=G->ADJ[k][j];
	    		shortedge[j].adjpeak=G->Peak[k];
			}
		}
	    
	 } 
}


int main() 
{
	PeakType start;
	 
	MG G;
	CreateUndig(&G);
	PrintADJ(G); 
	
	printf("请输入起始点为:");
	scanf(" %c",&start);
	printf("最小生成树为:\n");
	MiniSpanTree_Prim(&G,start);
	return 0;
}

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值