图的最小生成树算法实现(Prim + Kruskal)

1、采用书上第 161 页定义的图的邻接矩阵存储表示,编程实现构造最小生成树的 Prim 算法。

2、采用书上第 161 页定义的图的邻接矩阵存储表示,编程实现构造最小生成树的 Kruskal 算法。

例题一(Prim 算法实现):

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM 20
typedef int Status;
typedef int VRType;
typedef int infoType;
typedef enum{DG,DN,UDG,UDN}GraphKind;
typedef struct ArcCell
{
	VRType adj;
	infoType* info;
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef char VertexType;
typedef struct
{
	VertexType vexs[MAX_VERTEX_NUM];
	AdjMatrix arcs;
	int vexnum, arcnum;
	GraphKind kind;
}MGraph;

typedef struct {
	VertexType adjvex;
	VRType lowcost;
}Closedge[MAX_VERTEX_NUM];

int LocateVex(MGraph G, char v)
{
	int i;
	for (int i = 0; i < G.vexnum; i++)
		if (G.vexs[i] == v)	return i;
	return -1;
}
Status CreateDG(MGraph& G)
{
	int i, j, k;
	VertexType v1, v2;
	printf("输入顶点数G.vexnum: ");		scanf("%d", &G.vexnum);
	printf("输入边数G.arcnum: ");		scanf("%d", &G.arcnum);
	getchar();
	for (i = 0; i < G.vexnum; i++)
	{
		printf("输入顶点G.vexs[%d]:", i);
		scanf("%c", &G.vexs[i]);
		getchar();
	}
	for (i = 0; i < G.vexnum; i++)
		for (j = 0; j < G.vexnum; j++)
		{
			G.arcs[i][j].adj = 0;
			G.arcs[i][j].info = NULL;
		}
	for (k = 0; k < G.arcnum; k++)
	{
		printf("输入第%d条边vi、vj:\n", k + 1);
		scanf("%c %c", &v1, &v2);
		getchar();
		i = LocateVex(G, v1);	j = LocateVex(G, v2);
		G.arcs[i][j].adj = 1;
	}
	return OK;
}
Status CreateUDG(MGraph& G)
{
	int i, j, k;
	VertexType v1, v2;
	printf("输入顶点数G.vexnum: ");		scanf("%d", &G.vexnum);
	printf("输入边数G.arcnum: ");		scanf("%d", &G.arcnum);
	getchar();
	for (i = 0; i < G.vexnum; i++)
	{
		printf("输入顶点G.vexs[%d]:", i);
		scanf("%c", &G.vexs[i]);
		getchar();
	}
	for (i = 0; i < G.vexnum; i++)
		for (j = 0; j < G.vexnum; j++)
		{
			G.arcs[i][j].adj = 0;
			G.arcs[i][j].info = NULL;
		}
	for (k = 0; k < G.arcnum; k++)
	{
		printf("输入第%d条边vi、vj:\n", k + 1);
		scanf("%c %c", &v1, &v2);
		getchar();
		i = LocateVex(G, v1);	j = LocateVex(G, v2);
		G.arcs[i][j].adj = 1;
		G.arcs[j][i].adj = G.arcs[i][j].adj;
	}
	return OK;
}
Status CreateUDN(MGraph& G)
{
	int i, j, k, w;
	VertexType v1, v2;
	printf("输入顶点数G.vexnum: ");		scanf("%d", &G.vexnum);
	printf("输入边数G.arcnum: ");		scanf("%d", &G.arcnum);
	getchar();
	for (i = 0; i < G.vexnum; i++)
	{
		printf("输入顶点G.vexs[%d]:",i);
		scanf("%c", &G.vexs[i]);
		getchar();
	}
	for(i=0;i<G.vexnum;i++)
		for (j = 0; j < G.vexnum; j++)
		{
			G.arcs[i][j].adj = INFINITY;
			G.arcs[i][j].info = NULL;
		}
	for (k = 0; k < G.arcnum; k++)
	{
		printf("输入第%d条边vi、vj和权值w(int):\n", k + 1);
		scanf("%c %c %d", &v1, &v2, &w);
		getchar();
		i = LocateVex(G, v1);	j = LocateVex(G, v2);
		G.arcs[i][j].adj = w;
		G.arcs[j][i].adj = G.arcs[i][j].adj;
	}
	return OK;
}
Status CreateDN(MGraph& G)
{
	int i, j, k, w;
	VertexType v1, v2;
	printf("输入顶点数G.vexnum: ");		scanf("%d", &G.vexnum);
	printf("输入边数G.arcnum: ");		scanf("%d", &G.arcnum);
	getchar();
	for (i = 0; i < G.vexnum; i++)
	{
		printf("输入顶点G.vexs[%d]:", i);
		scanf("%c", &G.vexs[i]);
		getchar();
	}
	for (i = 0; i < G.vexnum; i++)
		for (j = 0; j < G.vexnum; j++)
		{
			G.arcs[i][j].adj = INFINITY;
			G.arcs[i][j].info = NULL;
		}
	for (k = 0; k < G.arcnum; k++)
	{
		printf("输入第%d条边vi、vj和权值w(int):\n", k + 1);
		scanf("%c %c %d", &v1, &v2, &w);
		getchar();
		i = LocateVex(G, v1);	j = LocateVex(G, v2);
		G.arcs[i][j].adj = w;
	}
	return OK;
}
Status CreateGraph(MGraph& G)
{
	printf("请输入图的种类:0表示DG,1表示DN,2表示UDG,3表示UDN\n");
	scanf("%d", &G.kind);
	switch (G.kind)
	{
	case DG:return CreateDG(G);
	case DN:return CreateDN(G);
	case UDG:return CreateUDG(G);
	case UDN:return CreateUDN(G);
	default:return ERROR;
	}
}
void list(MGraph G)
{
	int i, j;
	printf("输出邻接矩阵:\n");
	for (i = 0; i < G.vexnum; i++)
	{
		printf("%c----", G.vexs[i]);
		for (j = 0; j < G.vexnum; j++)
			if (G.arcs[i][j].adj == INFINITY)
				{printf("%4s", "∞"); }
			else
				printf("%4d", G.arcs[i][j].adj);
		printf("\n");
	}
}
Status minimum(MGraph G,Closedge closedge)
{
	int i, j;
	double k = 1000;
	for (i = 0; i < G.vexnum; i++)
	{
		if (closedge[i].lowcost != 0 && closedge[i].lowcost < k)
		{
			k = closedge[i].lowcost;
			j = i;
		}
	}
	return j;
}

void MiniSpanTree_PRIM(MGraph G, VertexType u) {
	int i, j,k;
	Closedge closedge;
	k = LocateVex(G, u);
	for (j = 0; j < G.vexnum; ++j)
		if (j != k) closedge[j] = { u,G.arcs[k][j].adj };
	closedge[k].lowcost = 0;
	for (i = 1; i < G.vexnum; ++i)
	{
		k = minimum(G,closedge);
		printf("%c%c ",closedge[k].adjvex, G.vexs[k]);
		closedge[k].lowcost = 0;
		for (j = 0; j < G.vexnum;++j) 
			if (G.arcs[k][j].adj < closedge[j].lowcost)
				closedge[j] = { G.vexs[k],G.arcs[k][j].adj };
		}
	}
	
int main()
{
    MGraph G;
	CreateGraph(G);
	list(G);
	printf("输出最小生成树:\n");
    MiniSpanTree_PRIM(G, 'A');
    printf("\n");
}

例题二(Kruskal 算法实现):

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM 20
typedef int Status;
typedef int VRType;
typedef int infoType;
typedef char VertexType;
typedef struct ArcCell
{
	VRType adj;
	VertexType start, finish;
}ArcCell, AdjMatrix[MAX_VERTEX_NUM];
typedef struct
{
	VertexType vexs[MAX_VERTEX_NUM];
	AdjMatrix arcs;
	int vexnum, arcnum;
}MGraph;
int LocateVex(MGraph G, char v)
{
	int i;
	for (int i = 0; i < G.vexnum; i++)
		if (G.vexs[i] == v)	return i;
	return -1;
}
Status CreateGraph(MGraph& G)
{
	int i, j, k, w;
	VertexType v1, v2;
	printf("输入顶点数G.vexnum: ");		scanf("%d", &G.vexnum);
	printf("输入边数G.arcnum: ");		scanf("%d", &G.arcnum);
	getchar();
	for (i = 0; i < G.vexnum; i++)
	{
		printf("输入顶点G.vexs[%d]:", i);
		scanf("%c", &G.vexs[i]);
		getchar();
	}
	for (k = 0; k < G.arcnum; k++)
	{
		printf("输入第%d条边vi、vj和权值w(int):\n", k + 1);
		scanf("%c %c %d", &v1, &v2, &w);
		getchar();
		G.arcs[k].start = v1;	G.arcs[k].finish = v2;
		G.arcs[k].adj = w;
	}
	for (i = 0; i < G.arcnum-1; i++)
	{
		for (j = i + 1; j < G.arcnum; j++)
		{
			ArcCell Temp;
			if (G.arcs[i].adj > G.arcs[j].adj)
			{
				Temp = G.arcs[i];	G.arcs[i] = G.arcs[j];	G.arcs[j] = Temp;
			}
		}
	}
	return OK;
}
Status FindStuation(int partern[], int e)
{
	while (partern[e] != 0)
	{
		e = partern[e];
	}
	return e;
}
Status FinishFind(MGraph& G, int partern[])
{
	int i, num = 0;
	for (i = 0; i < G.vexnum; i++)
	{
		if (partern[i])	num++;
	}
	if (num == G.vexnum - 1)	return OK;
	return FALSE;
}
Status MiniSpanTree_Kruskal(MGraph& G)
{
	int i, sit, hit;
	int partern[MAX_VERTEX_NUM];
	for (i = 0; i < G.vexnum; i++)
	{
		partern[i] = 0;
	}
	for (i = 0; i < G.arcnum; i++)
	{
		sit = FindStuation(partern,LocateVex(G,G.arcs[i].start));
		hit = FindStuation(partern,LocateVex(G,G.arcs[i].finish));
		if (sit != hit)
		{
			partern[sit] = hit;
			printf("%c%c ", G.arcs[i].start, G.arcs[i].finish);
		}
		if(FinishFind(G,partern))	return OK;
	}
}
int main()
{
	MGraph G;
	CreateGraph(G);
	printf("输出最小生成树:\n");
	MiniSpanTree_Kruskal(G);
	printf("\n");
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值