#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;
}
原图:
输入:
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
结果: