C语言克鲁斯卡尔算法的实现

来源:互联网 发布:ip8823网络广播终端 编辑:程序博客网 时间:2024/06/05 07:53

        克鲁斯卡尔算法同样用于产生最小生成树。其实现代码如下:

        首先是预定义和类型定义:

#define OK 1#define ERROR 0#define Max_Int 32726#define MVNum 100typedef 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;}

1 0
原创粉丝点击