(C语言浙大版)Prim最小生成树算法(含测试用例)

本博文源于浙江大学《数据结构》,Prim算法是今天所学的,看起来这是一个贪心算法。我们先谈这个测试案例,看博主发生了什么
在这里插入图片描述
这是一张带权值的有向图,老师上课用的是这张
在这里插入图片描述
我傻傻的试着程序,一直没发现我是有向图做的最后代码实现效果是这样子的
在这里插入图片描述
这个测试结果怎么看,先看0 3,0 3代表 v0 跟v3有路。
1 后面没有值代表没有边跟他连
2 5代表v2跟v5相连,这就是看测试用例输出的细节。下面还是强调一下,我给出的

7 12
2 0 4
2 5 5
0 1 2
0 3 1
1 4 10
1 3 3
3 2 2
3 5 8
3 6 4
3 4 2
4 6 6
6 5 1

我给出的是有向图的输入用例,把它改成无向图大家应该都明白的,不明的看这个博文:
(C语言)图的邻接矩阵操作集(包含测试源码)
因为老师用的是两种图操作,所以代码冗长,希望大家能理解,大家要认真看仔细每个细节,prim算法本质就是完成最小生成树的创建,最小生成树创建的指标牢记于心,下面也再放图
在这里插入图片描述
所以大家用这三条标准检验你的输出到底是否符合,别用脑子去检查为什么有个权值更小他不走,非要走权值最大的。当大家把定义牢记于心,并且记住贪心贪的是局部最优,那么你离理解Prim算法之路就不远了。
下面放出源代码:

//还是Prime
#include<stdio.h>
#include<stdlib.h>
#define MaxVertexNum 10
#define false 0
#define true 1
#define ERROR -1
#define INFINITY 999999

typedef int WeightType;
typedef int DataType;
typedef struct MGNode *PtrToMGNode;
typedef int bool;
typedef int Position;

typedef int ElementType;

#include<stdio.h>
#include<stdlib.h>
#define MaxVertexNum 10
#define false 0
#define true 1
#define ERROR -1
typedef int Vertex;
typedef int WeightType;

typedef int ElementType;
typedef struct LENode *PtrToLENode;


struct LENode {
	Vertex V1, V2;
	WeightType Weight;
};
typedef PtrToLENode LEdge;

typedef struct AdjVNode *PtrToAdjVNode;


struct AdjVNode {
	Vertex AdjV; // 邻接点的下标
	WeightType Weight;//边的权重
	PtrToAdjVNode Next;
};

typedef struct Vnode{
	PtrToAdjVNode FirstEdge;
	DataType Data;//存顶点得数据
}AdjList[MaxVertexNum];

typedef struct GNode *PtrToGNode;
struct GNode {
	int Nv;//顶点数
	int Ne;//边数
	AdjList G;//邻接表
};
typedef PtrToGNode LGraph;


LGraph CreateLGraph(int VertexNum)
{
	Vertex V;
	LGraph Graph;
	
	Graph = (LGraph)malloc(sizeof(struct GNode));
	Graph->Nv = VertexNum;
	Graph->Ne = 0;
	
	for(V = 0;V<Graph->Nv;V++){
		Graph->G[V].FirstEdge = NULL;
		Graph->G[V].Data = V;
	}
	
	return Graph;
}

void InsertLEdge(LGraph Graph, LEdge E)
{
	PtrToAdjVNode NewNode;
	
	NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
	NewNode->AdjV = E->V2;
	NewNode->Weight = E->Weight;
	//将v2插入v1的表头
	NewNode->Next = Graph->G[E->V1].FirstEdge;
	Graph->G[E->V1].FirstEdge = NewNode;
	

}

LGraph BuildLGraph()
{
	LGraph Graph;
	LEdge E;
	Vertex V;
	int Nv,i;
	scanf("%d",&Nv);//读入顶点个数
	Graph = CreateLGraph(Nv);//初始化有Nv个顶点但没有边的图
	
	scanf("%d",&(Graph->Ne));
	if(Graph->Ne != 0)
	{
		E = (LEdge)malloc(sizeof(struct LENode));
		for(i=0;i<Graph->Ne;i++)
		{
			scanf("%d %d %d",&E->V1,&E->V2,&E->Weight);
			InsertLEdge(Graph, E);
			
		}
	}
	

	
	return Graph;
}






struct MGNode {
	int Nv;  //一张图的顶点数
	int Ne; //一张图的边数
	WeightType G[MaxVertexNum][MaxVertexNum];
	DataType Data[MaxVertexNum];//存顶点的数据
};
typedef PtrToMGNode MGraph;//以邻接矩阵存储的图类型

//初始化一个有VertexNum 个顶点但没有边的图
typedef int Vertex;//用顶点下标表示顶点,为整型
MGraph CreateMGraph(int VertexNum)
{
	Vertex V, W;
	MGraph Graph;
	
	Graph = (MGraph)malloc(sizeof(struct MGNode));
	Graph->Nv = VertexNum;
	Graph->Ne = 0;
	
	//注意:这里默认顶点编号从0开始,到(Graph->Nv-1)
	for(V=0; V<Graph->Nv;V++)
		for(W=0; W<Graph->Nv;W++)
			Graph->G[V][W] = INFINITY;
	for(int i =0;i<Graph->Nv;i++)
	{
	
		Graph->Data[i]=i;
	}
	return Graph;
	
}
typedef struct ENode *PtrToENode;
struct ENode {
	Vertex V1,V2;//有向边<V1,V2>
	WeightType Weight;//权值
};
typedef PtrToENode Edge;



void InsertMEdge(MGraph Graph, Edge E)
{
	Graph->G[E->V1][E->V2] = E->Weight;
	Graph->G[E->V2][E->V1] = E->Weight;
}


MGraph BuildMGraph()
{
	
	MGraph Graph;
	Edge E;
	Vertex V;
	int Nv,i;
	scanf("%d",&Nv);
	Graph = CreateMGraph(Nv);
	scanf("%d",&(Graph->Ne));
	if(Graph->Ne != 0) {
		E = (Edge)malloc(sizeof(struct ENode));
		for(i=0;i<Graph->Ne;i++) {
			scanf("%d %d %d",&E->V1,&E->V2,&E->Weight);
			InsertMEdge(Graph, E);
		}
			
	}
	return Graph;
}

Vertex FindMinDist(MGraph Graph,WeightType dist[])
{
	Vertex MinV,V;
	WeightType MinDist = INFINITY;
	
	for(V=0;V<Graph->Nv;V++)
		if(dist[V] != 0 && dist[V] < MinDist) {
			MinDist = dist[V];
			MinV = V;
		}
	if(MinDist < INFINITY)
		return MinV;
	else 
		return -1;
}

int Prim(MGraph Graph) {
	WeightType dist[MaxVertexNum],TotalWeight;
	Vertex parent[MaxVertexNum],V,W;
	int VCount;
	LEdge E;
	
	for(V=0;V<Graph->Nv;V++) {
		dist[V] = Graph->G[0][V];
		parent[V] = 0;
	}
	TotalWeight = 0;
	VCount = 0;
	LGraph MST = CreateLGraph(Graph->Nv);
	E = (LEdge) malloc(sizeof(struct LENode));
	
	dist[0] = 0;
	VCount ++;
	parent[0] = -1;
	
	while(1) {
		V = FindMinDist(Graph,dist);
		if(V == -1)
			break;
		E->V1 = parent[V];
		E->V2 = V;
		E->Weight = dist[V];
		InsertLEdge(MST,E);
		TotalWeight += dist[V];
		dist[V] = 0;
		VCount ++;
		
		for(W=0;W<Graph->Nv;W++)
			if(dist[W] != 0 && Graph->G[V][W] < INFINITY) {
				dist[W] = Graph->G[V][W];
				parent[W] = V;
			}
	}
	if(VCount < Graph->Nv)
		TotalWeight = -1;
		for(int i =0;i<Graph->Nv;i++)
	{
			PtrToAdjVNode NewNode;
			NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
			NewNode->Next = MST->G[i].FirstEdge;
			printf("%d ",MST->G[i].Data);
			NewNode = NewNode->Next;
			while(NewNode != NULL)
			{
				printf("%d ",NewNode->AdjV);
				NewNode = NewNode->Next;
				
			}
			printf("\n");
		
	}
	return TotalWeight;
}
int main()
{
	MGraph Graph = BuildMGraph();
	int Nv = Graph->Nv;
	printf("\n\n\n\n-----List Traverse---------\n\n\n\n");
	LGraph MST;
	int flag = Prim(Graph);
	// for(int i =0;i<Nv;i++)
	// {
			// PtrToAdjVNode NewNode;
			// NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
			// NewNode->Next = MST->G[i].FirstEdge;
			// printf("%d ",MST->G[i].Data);
			// NewNode = NewNode->Next;
			// while(NewNode != NULL)
			// {
				// printf("%d ",NewNode->AdjV);
				// NewNode = NewNode->Next;
				
			// }
			// printf("\n");
		
	// }

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值