数据结构克鲁斯卡尔算法

#include <stdio.h>
#include <string.h>
#define OK 1
#define INFINITY 32767
#define MAX_VERTEX_NUM 30
#define MAXINFOLEN 30
#define ERROR 0
#define OVERFLOW -1
#define MAXVERTEXLEN 30
#define FALSE 0
#define TRUE 1
typedef int Status;
typedef enum { DG, DN, UDG, UDN }GraphKind;
typedef int VRType;
typedef int InfoType;
typedef char* VertexType;
typedef struct ArcCell
{
	VRType adj;
	InfoType* info;
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
	VertexType vexs[MAX_VERTEX_NUM];
	AdjMatrix arcs;
	int vexnum, arcnum;
	GraphKind kind;
}MGraph;
Status CreatGraph(MGraph* G)
{
	printf("请输入图的类型\n");
	scanf("%d", &(G->kind));
	switch (G->kind)
	{
	case DG:return(CreatDG(G)); break;
	case DN:return(CreatDN(G)); break;
	case UDG:return(CreatUDG(G)); break;
	case UDN:return(CreatUDN(G)); break;
	default: return ERROR;
	}
}
Status CreatDG(MGraph* G)
{
	printf("请依次输入图的总结点数,弧数,以及是弧是否需要额外信息,无额外信息输入0,有额外信息输入1\n");
	int info;
	scanf("%d%d%d", &(G->vexnum), &(G->arcnum), &info);
	getchar();
	printf("请输入%d个顶点的描述\n", G->vexnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		G->vexs[i] = (VertexType)malloc(sizeof(char) * MAXVERTEXLEN);
		if (!G->vexs[i]) exit(OVERFLOW);
		gets(G->vexs[i]);
	}
	for(int i=0;i<G->vexnum;i++)
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = 0;
			G->arcs[i][j].info = NULL;
		}
	int tail, head;
	char* ch;
	ch = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
	if (!ch) exit(OVERFLOW);
	for (int i = 0; i < G->arcnum; i++)
	{
		printf("请输入第%d个顶点关系\n", i + 1);
		printf("请输入它的弧尾顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				tail = j;
				break;
			}
		printf("请输入它的弧头顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				head = j;
				break;
			}
		G->arcs[tail][head].adj = 1;
		if (info)
		{
			G->arcs[tail][head].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[tail][head].info) exit(OVERFLOW);
			printf("请输入其信息\n");
			gets(G->arcs[tail][head].info);
		}
	}
	return OK;
}
Status CreatDN(MGraph* G)
{
	printf("请依次输入图的总结点数,弧数,以及是弧是否需要额外信息,无额外信息输入0,有额外信息输入1\n");
	int info;
	scanf("%d%d%d", &(G->vexnum), &(G->arcnum), &info);
	getchar();
	printf("请输入%d个顶点的描述\n", G->vexnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		G->vexs[i] = (VertexType)malloc(sizeof(char) * MAXVERTEXLEN);
		if (!G->vexs[i]) exit(OVERFLOW);
		gets(G->vexs[i]);
	}
	for (int i = 0; i < G->vexnum; i++)
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = INFINITY;
			G->arcs[i][j].info = NULL;
		}
	int tail, head;
	char* ch;
	ch = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
	if (!ch) exit(OVERFLOW);
	for (int i = 0; i < G->arcnum; i++)
	{
		printf("请输入第%d个顶点关系\n", i + 1);
		printf("请输入它的弧尾顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				tail = j;
				break;
			}
		printf("请输入它的弧头顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				head = j;
				break;
			}
		printf("请输入弧的权值\n");
		scanf("%d", &(G->arcs[tail][head]));
		getchar();
		if (info)
		{
			G->arcs[tail][head].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[tail][head].info) exit(OVERFLOW);
			printf("请输入其信息\n");
			gets(G->arcs[tail][head].info);
		}
	}
	return OK;
}
Status CreatUDG(MGraph* G)
{
	printf("请依次输入图的总结点数,弧数,以及是弧是否需要额外信息,无额外信息输入0,有额外信息输入1\n");
	int info;
	scanf("%d%d%d", &(G->vexnum), &(G->arcnum), &info);
	getchar();
	printf("请输入%d个顶点的描述\n", G->vexnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		G->vexs[i] = (VertexType)malloc(sizeof(char) * MAXVERTEXLEN);
		if (!G->vexs[i]) exit(OVERFLOW);
		gets(G->vexs[i]);
	}
	for (int i = 0; i < G->vexnum; i++)
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = 0;
			G->arcs[i][j].info = NULL;
		}
	int vex1, vex2;
	char* ch;
	ch = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
	if (!ch) exit(OVERFLOW);
	for (int i = 0; i < G->arcnum; i++)
	{
		printf("请输入第%d个顶点关系\n", i + 1);
		printf("请输入它所依附的第一个顶点的顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				vex1 = j;
				break;
			}
		printf("请输入它所依附的第二个顶点的顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				vex2 = j;
				break;
			}
		G->arcs[vex1][vex2].adj = 1;
		G->arcs[vex2][vex1].adj = 1;
		if (info)
		{
			G->arcs[vex1][vex2].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[vex1][vex2].info) exit(OVERFLOW);
			printf("请输入其信息\n");
			gets(G->arcs[vex1][vex2].info);
			G->arcs[vex2][vex1].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[vex2][vex1].info) exit(OVERFLOW);
			strcpy(G->arcs[vex2][vex1].info, G->arcs[vex1][vex2].info);
		}
	}
	return OK;
}
Status CreatUDN(MGraph* G)
{
	printf("请依次输入图的总结点数,弧数,以及是弧是否需要额外信息,无额外信息输入0,有额外信息输入1\n");
	int info;
	scanf("%d%d%d", &(G->vexnum), &(G->arcnum), &info);
	getchar();
	printf("请输入%d个顶点的描述\n", G->vexnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		G->vexs[i] = (VertexType)malloc(sizeof(char) * MAXVERTEXLEN);
		if (!G->vexs[i]) exit(OVERFLOW);
		gets(G->vexs[i]);
	}
	for (int i = 0; i < G->vexnum; i++)
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = INFINITY;
			G->arcs[i][j].info = NULL;
		}
	int vex1, vex2;
	char* ch;
	ch = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
	if (!ch) exit(OVERFLOW);
	for (int i = 0; i < G->arcnum; i++)
	{
		printf("请输入第%d个顶点关系\n", i + 1);
		printf("请输入它所依附的第一个顶点的顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				vex1 = j;
				break;
			}
		printf("请输入它所依附的第二个顶点的顶点描述\n");
		gets(ch);
		for (int j = 0; j < G->vexnum; j++)
			if (strcmp(ch, G->vexs[j]) == 0)
			{
				vex2 = j;
				break;
			}
		printf("请输入此弧权值\n");
		scanf("%d", &(G->arcs[vex1][vex2].adj));
		getchar();
		G->arcs[vex2][vex1].adj = G->arcs[vex1][vex2].adj;
		if (info)
		{
			G->arcs[vex1][vex2].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[vex1][vex2].info) exit(OVERFLOW);
			printf("请输入其信息\n");
			gets(G->arcs[vex1][vex2].info);
			G->arcs[vex2][vex1].info = (InfoType*)malloc(sizeof(InfoType) * MAXINFOLEN);
			if (!G->arcs[vex2][vex1].info) exit(OVERFLOW);
			strcpy(G->arcs[vex2][vex1].info, G->arcs[vex1][vex2].info);
		}
	}
	return OK;
}
//树的双亲表示法
typedef char* TElemType;
#define MAX_TREE_SIZE 100
typedef struct PTNode
{
	TElemType data;
	int parent;
}PTNode;
typedef struct
{
	PTNode nodes[MAX_TREE_SIZE];
	int r, n;
}PTree;
//并查集相关数据结构
typedef PTree MFSet;
int Find_MFSet(MFSet S, int i)            //找出集合S中i所在子集的根
{
	if (i < 0 || i >= S.n)
		return ERROR;
	int k = i;
	while (S.nodes[k].parent > 0)
		k = S.nodes[k].parent;
	return k;
}
Status Merge_MFSet(MFSet* S, int i, int j)
{
	int iroot = Find_MFSet(*S, i), jroot = Find_MFSet(*S, j);
	if (iroot != jroot)
	{
		if (S->nodes[iroot].parent < S->nodes[jroot].parent)
		{
			S->nodes[iroot].parent += S->nodes[jroot].parent;
			S->nodes[jroot].parent = iroot;
		}
		else
		{
			S->nodes[jroot].parent += S->nodes[iroot].parent;
			S->nodes[iroot].parent = jroot;
		}
	}
	return OK;
}
void MinSpanTree_Kruskal(MGraph G, VertexType u)
{
	MFSet S;
	S.n = G.vexnum;
	for (int i = 0; i < G.vexnum; i++)
		if (strcmp(u, G.vexs[i]) == 0)
		{
			S.r = i;
			break;
		}
	for (int i = 0; i < G.vexnum; i++)
	{
		S.nodes[i].data = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
		if (!S.nodes[i].data) exit(OVERFLOW);
		strcpy(S.nodes[i].data, G.vexs[i]);
		S.nodes[i].parent = -1;
	}
	int count = 1;
	while (count < G.vexnum)
	{
		int minrow, mincol, min = INFINITY;
		for (int i = 0; i < G.vexnum; i++)
		{
			for (int j = i; j < G.vexnum; j++)
			{
				if (G.arcs[i][j].adj && G.arcs[i][j].adj < min)
				{
					minrow = i;
					mincol = j;
					min = G.arcs[i][j].adj;
				}
			}
		}
		G.arcs[minrow][mincol].adj = 0;
		if (Find_MFSet(S, minrow) != Find_MFSet(S, mincol))
		{
			printf("将%s与%s连起来\n", G.vexs[minrow], G.vexs[mincol]);
			Merge_MFSet(&S, minrow, mincol);
			count++;
		}
	}
}
//克鲁斯卡尔算法主函数
int main()
{
	MGraph G;
	CreatGraph(&G);
	printf("\t");
	for (int i = 0; i < G.vexnum; i++)
		printf("V%d\t", i + 1);
	printf("\n\n");
	for (int i = 0; i < G.vexnum; i++)
	{
		printf("V%d\t", i + 1);
		for (int j = 0; j < G.vexnum; j++)
			printf("%d\t", G.arcs[i][j].adj);
		printf("\n\n\n");
	}
	char* u = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
	if (!u) exit(OVERFLOW);
	strcpy(u, G.vexs[0]);
	MinSpanTree_Kruskal(G, u);
	return 0;
}

原图:

kruskal

 输入:

3
6 10 0
V1
V2
V3
V4
V5
V6
V1
V2
6
V1
V3
1
V1
V4
5
V2
V3
5
V3
V4
5
V2
V5
3
V3
V5
6
V5
V6
6
V3
V6
4
V4
V6
2

结果:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值