#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;
typedef struct CSNode
{
TElemType data;
struct CSNode* firstchild, * nextsibling;
}CSNode, * CSTree;
//队列函数
typedef CSTree QElemType;
typedef struct QNode
{
QElemType data;
struct QNode* next;
}QNode, * QueuePtr;
typedef struct
{
QueuePtr front, rear;
}LinkQueue;
Status InitQueue(LinkQueue* Q)
{
Q->front = (QNode*)malloc(sizeof(QNode));
if (!Q->front) exit(OVERFLOW);
Q->rear = Q->front;
return OK;
}
Status EnQueue(LinkQueue* Q, QElemType e)
{
QNode* p;
p = (QNode*)malloc(sizeof(QNode));
if (!p) exit(OVERFLOW);
p->data = e;
Q->rear->next = p;
Q->rear = p;
p->next = NULL;
return OK;
}
Status DeQueue(LinkQueue* Q, QElemType* e)
{
if (Q->front == Q->rear)
return ERROR;
*e = Q->front->next->data;
if (Q->rear == Q->front->next)
Q->rear = Q->front;
QNode* p = Q->front->next;
Q->front->next = p->next;
free(p);
return OK;
}
Status QueueEmpty(LinkQueue Q)
{
if (Q.front == Q.rear)
return TRUE;
else
return FALSE;
}
void PrintQueue(LinkQueue Q)
{
QNode* p = Q.front->next;
if (!p)
printf("空\n");
else
{
while (p)
{
printf("%d\t", p->data + 1);
p = p->next;
}
printf("\n");
}
}
void PrintCSTree_LevelOrder(CSTree T)
{
printf("孩子兄弟树层序输入为\n");
LinkQueue* Q;
Q = (LinkQueue*)malloc(sizeof(LinkQueue));
if (!Q) exit(OVERFLOW);
InitQueue(Q);
EnQueue(Q, T);
QElemType* p;
p = (QElemType*)malloc(sizeof(QElemType));
if (!p) exit(OVERFLOW);
while (!QueueEmpty(*Q))
{
DeQueue(Q, p);
puts((*p)->data);
if ((*p)->firstchild)
EnQueue(Q, (*p)->firstchild);
if ((*p)->nextsibling)
EnQueue(Q, (*p)->nextsibling);
}
}
//栈的数据结构及函数
#define STACK_INIT_SIZE 100
#define STACK_INCREASMENT 10
typedef int SElemType;
typedef struct
{
SElemType* base, * top;
int stacksize;
}SqStack;
Status InitStack(SqStack* S)
{
S->base = (SElemType*)malloc(sizeof(SElemType) * STACK_INIT_SIZE);
if (!S->base) exit(OVERFLOW);
S->top = S->base;
S->stacksize = STACK_INIT_SIZE;
}
Status Push(SqStack* S, SElemType e)
{
if (S->top - S->base > S->stacksize)
{
S->base = (SElemType*)realloc(S->base, sizeof(SElemType) * (S->stacksize + STACK_INCREASMENT));
if (!S->base) exit(OVERFLOW);
S->stacksize += STACK_INCREASMENT;
}
*(S->top) = e;
S->top++;
return OK;
}
Status Pop(SqStack* S, SElemType* e)
{
if (S->base == S->top)
return ERROR;
S->top--;
*e = *(S->top);
return OK;
}
Status StackEmpty(SqStack S)
{
if (S.base == S.top)
return TRUE;
else
return FALSE;
}
void PreOrderTraverse_MinSpanTree(CSTree* T, char* ch, CSTree* p)
{
SqStack S;
InitStack(&S);
CSNode* q = (*T);
while (q || !StackEmpty(S))
{
if (q)
{
Push(&S, q);
if (strcmp(ch, q->data) == 0)
{
*p = (CSTree)malloc(sizeof(CSNode));
if (!(*p)) exit(OVERFLOW);
*p = q;
break;
}
q = q->firstchild;
}
else
{
Pop(&S, &q);
q = q->nextsibling;
}
}
}
void MinSpanTree(MGraph G, VertexType u, CSTree* T)
{
struct
{
VertexType adjvex;
VRType lowcost;
}closeedge[MAX_VERTEX_NUM];
int k;
for (int i = 0; i < G.vexnum; i++)
if (strcmp(u, G.vexs[i]) == 0)
{
k = i;
break;
}
for (int i = 0; i < G.vexnum; i++)
{
if (i != k)
{
closeedge[i].lowcost = G.arcs[k][i].adj;
closeedge[i].adjvex = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
if (!closeedge[i].adjvex) exit(OVERFLOW);
strcpy(closeedge[i].adjvex, u);
}
}
(*T) = (CSTree)malloc(sizeof(CSNode));
if (!(*T)) exit(OVERFLOW);
(*T)->data = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
if (!(*T)->data) exit(OVERFLOW);
strcpy((*T)->data, u);
(*T)->firstchild = NULL;
(*T)->nextsibling = NULL;
closeedge[k].lowcost = 0;
closeedge[k].adjvex = NULL;
int count = 1;
char* ch;
ch = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
if (!ch) exit(OVERFLOW);
CSNode* p;
while (count < G.vexnum)
{
int mincost = INFINITY;
int min;
for (int i = 0; i < G.vexnum; i++)
if (closeedge[i].lowcost && closeedge[i].lowcost < mincost)
{
mincost = closeedge[i].lowcost;
min = i;
}
strcpy(ch, closeedge[min].adjvex);
PreOrderTraverse_MinSpanTree(T, ch, &p); //在树T中找到与ch相同的节点并返回它的指针
CSNode* q;
q = (CSNode*)malloc(sizeof(CSNode));
if (!q) exit(OVERFLOW);
q->data = (char*)malloc(sizeof(char) * MAXVERTEXLEN);
if (!q->data) exit(OVERFLOW);
strcpy(q->data, G.vexs[min]);
if (p->firstchild)
{
p = p->firstchild;
while (p->nextsibling)
p = p->nextsibling;
p->nextsibling = q;
q->firstchild = NULL;
q->nextsibling = NULL;
}
else
{
p->firstchild = q;
q->nextsibling = NULL;
q->firstchild = NULL;
}
closeedge[min].lowcost = 0;
closeedge[min].adjvex = NULL;
for (int j = 0; j < G.vexnum; j++)
if (closeedge[j].lowcost && G.arcs[min][j].adj < closeedge[j].lowcost)
{
closeedge[j].lowcost = G.arcs[min][j].adj;
strcpy(closeedge[j].adjvex, G.vexs[min]);
}
count++;
}
}
//Prim算法主函数
int main()
{
MGraph G;
CSTree* T;
T = (CSTree*)malloc(sizeof(CSTree));
if (!T) exit(OVERFLOW);
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(G, u, T);
PrintCSTree_LevelOrder(*T);
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
原图:
结果: