克鲁斯卡尔算法同样用于产生最小生成树。其实现代码如下:
首先是预定义和类型定义:
#define OK 1
#define ERROR 0
#define Max_Int 32726
#define MVNum 100
typedef int Status;
typedef int ArcType;
typedef char VerTexType;
struct ed{
VerTexType Head;
VerTexType Tail;
ArcType lowcost;
}Edge[MVNum];
typedef struct{
VerTexType vex[MVNum];
ArcType arc[MVNum][MVNum];
int arcnum, vexnum;
}AMGraph;
其中,Edge[]数组用于储存各条边的信息(包括头尾节点和权值)。
创建图:
int LocateVex(AMGraph *G, VerTexType v)
{
int i;
for (i = 0; i < G->vexnum; i++)
{
if (G->vex[i] == v)
return i;
}
return -1;
}
Status CreateUDN(AMGraph *G)
{
VerTexType v1, v2;
ArcType w;
int i, j, k;
printf("输入总节点数、总边数:");
scanf("%d %d", &G->vexnum, &G->arcnum);
printf("输入节点的值:");
fflush(stdin);
for (i = 0; i < G->vexnum; i++)
{
scanf("%c", &G->vex[i]);
}
for (i = 0; i < G->vexnum; i++)
for (j = 0; j < G->vexnum; j++)
{
G->arc[i][j] = Max_Int;
}
for (k = 0; k < G->arcnum; k++)
{
fflush(stdin);
printf("依次输入边的两个顶点以及边的权值:");
scanf("%c %c %d", &v1, &v2, &w);
Edge[k].Head = v1;
Edge[k].Tail = v2;
Edge[k].lowcost = w;
i = LocateVex(G, v1);
j = LocateVex(G, v2);
G->arc[i][j] = w;
G->arc[j][i] = G->arc[i][j];
}
return OK;
}
这里和之前创建邻接矩阵算法没有太大差别,只是要注意在输入节点信息的时候同时将节点信息储存在Edge[]数组中。
对Edge[]数组的排序:
void Sort(AMGraph G)
{
int i, j, addr;
ArcType min;
ed temp;
for (i = 0; i < G.arcnum; i++)
{
min = Edge[i].lowcost;
addr = i;
for (j = i + 1; j < G.arcnum; j++)
{
if (min>Edge[j].lowcost)
{
min = Edge[j].lowcost;
addr = j;
}
}
if (addr != i)
{
temp = Edge[i];
Edge[i] = Edge[addr];
Edge[addr] = temp;
}
}
}
根据各条边的权值大小进行简单的排序,不多加解释。
克鲁斯卡尔算法:
void MiniSpanTree_Kruskal(AMGraph G)
{
int i, j,v1,v2,vs1,vs2;
int *Vexset;
Sort(G);
Vexset = (int *)malloc(sizeof(int)*G.vexnum);
for (i = 0; i < G.vexnum; i++)
Vexset[i] = i;
for (i = 0; i < G.arcnum; i++)
{
v1 = LocateVex(&G, Edge[i].Head);
v2 = LocateVex(&G, Edge[i].Tail);
vs1 = Vexset[v1];
vs2 = Vexset[v2];
if (vs1 != vs2)
{
printf("%c->%c\n", Edge[i].Head, Edge[i].Tail);
for (j = 0; j < G.vexnum; j++)
{
if (Vexset[j] == vs2)
Vexset[j] = vs1;
}
}
}
}
对Edge[]数组进行排序,得到权值从小到大的数组。并声明一个用于记录是否是同一个连通分量的数组Vexset[](由于避免空间浪费,本人为其动态分配空间)。初始化Vexset[],让下标为i的元素的值为i,表示各自是一个连通分量。然后利用for()循环,依次读取边权值最小的边,判断其是否在同一个连通分量内,若不是,则输出并将其Vexset[]内的数值统一标记,表示为同一个连通分量。
加入main():
int main(void)
{
AMGraph G;
CreateUDN(&G);
MiniSpanTree_Kruskal(G);
return 0;
}