(1)Prim
算法如下,头文件:
#define INFINITY 10000
#define MAX_VERTEX_NUM 20
typedef int InfoType;
typedef char VertexType;
typedef int VRType;

typedef enum ...{DG, DN, UDG, UDN} GraphKind;

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;

int weight[][6] = ...{
...{0, 6, 1, 5, INFINITY,INFINITY},
...{6, 0, 5, INFINITY, 3, INFINITY},
...{1, 5, 0, 5, 6, 4},
...{5, INFINITY, 5, 0, INFINITY, 2},
...{INFINITY, 3, 6, INFINITY, 0, 6},
...{INFINITY, INFINITY, 4, 2, 6, 0}
};
//#define INPUT 1

typedef struct ...{
int parent;
int cost;
}mst_prim_closedge;源文件:
#include "graph.h"
#include "stdio.h"
#include "stdlib.h"

void createDG(MGraph &g)...{}
void createDN(MGraph &g)...{}
void createUDG(MGraph &g)...{}

int locate(MGraph g, char name)...{
for(int i = 0; i < g.vexnum; i++)...{
if(name == g.vexs[i])...{
return i;
}
}
return -1;
}

void createUDN(MGraph &g)...{
#ifdef INPUT
printf("input the number of vertex and arcs: ");
scanf("%d %d", &g.vexnum, &g.arcnum);
fflush(stdin);
#else
printf("input the number of vertex: ");
scanf("%d", &g.vexnum);
fflush(stdin);
#endif
int i = 0, j = 0, k = 0;
printf("input the name of vertex: ");

for(i = 0; i < g.vexnum; i++)...{
scanf("%c", &g.vexs[i]);
fflush(stdin);
}

for(i = 0; i < g.vexnum; i++)...{
for(j = 0; j < g.vexnum; j++)...{
g.arcs[i][j].adj = INFINITY;
g.arcs[i][j].info = NULL;
}
}
#ifdef INPUT
char v1, v2;
int w;
printf("input the %d arcs v1 v2 and weight: ", g.arcnum);
for(k = 0; k < g.arcnum; k++)...{
scanf("%c %c %d", &v1, &v2, &w);
fflush(stdin);
i = locate(g, v1);
j = locate(g, v2);
g.arcs[i][j].adj = w;
}
#else
printf("now constructing the matrix of graph... ");
for(i = 0; i < g.vexnum; i++)...{
for(j = 0; j < g.vexnum; j++)...{
g.arcs[i][j].adj = weight[i][j];
}
}
#endif
}

void printGraph(MGraph g)...{
for(int i = 0; i < g.vexnum; i++)...{
for(int j = 0; j < g.vexnum; j++)...{
printf("%d ", g.arcs[i][j].adj);
}
printf(" ");
}
}

void createGragh(MGraph &g)...{
printf("please input the type of graph: ");
scanf("%d", &g.kind);

switch(g.kind)...{
case DG:
createDG(g);
break;
case DN:
createDN(g);
break;
case UDG:
createUDG(g);
break;
case UDN:
createUDN(g);
printGraph(g);
break;
}
}
//get the min cost vertice, return the index
int minimum(mst_prim_closedge *closedge, int n)...{
int ret = -1;
int retcost = INFINITY;
for(int i = 0; i < n; i++)...{
if(closedge[i].cost > 0 && closedge[i].cost < retcost)...{
ret = i;
retcost = closedge[i].cost;
}
}
return ret;
}

/**//**
* the prim algorithm of mst(minimum cost spanning tree)
* MGraph g: the graph
* char start: the start point
*/
void mst_prim(MGraph g, char start)...{
mst_prim_closedge *closedge =
(mst_prim_closedge *)malloc(sizeof(mst_prim_closedge) * g.vexnum);
//get the index of start
int index = locate(g, start);
//init the closest edge array
int i = 0;
for(; i < g.vexnum; i++)...{
closedge[i].parent = index;
closedge[i].cost = g.arcs[index][i].adj;
}
//choose the next n-1 vertex
printf("now the mst is: ");
int j = 0;
for(i = 1; i < g.vexnum; i++)...{
j = minimum(closedge, g.vexnum);
printf("%c, %c, %d ",
g.vexs[closedge[j].parent], g.vexs[j], closedge[j].cost);
//j join the U
closedge[j].cost = 0;
//update the closedge
for(int k = 0; k < g.vexnum; k++)...{
if(g.arcs[j][k].adj > 0 && 
g.arcs[j][k].adj < closedge[k].cost)...{
closedge[k].cost = g.arcs[j][k].adj;
closedge[k].parent = j;
}
}
}
}

void main()...{
MGraph g;
createGragh(g);
char start;
printf("input the start point of mst: ");
scanf("%c", &start);
mst_prim(g, start);
}程序的执行结果为:
please input the type of graph:
3
input the number of vertex:
6
input the name of vertex:
a
b
c
d
e
f
now constructing the matrix of graph...
0 6 1 5 10000 10000
6 0 5 10000 3 10000
1 5 0 5 6 4
5 10000 5 0 10000 2
10000 3 6 10000 0 6
10000 10000 4 2 6 0
input the start point of mst:
a
now the mst is:
a, c, 1
c, f, 4
f, d, 2
c, b, 5
b, e, 3
Press any key to continue算法的复杂度:从函数mst_prim()可知,时间复杂度为O(n*n),适用于求边稠密的network的mst。
(2)Kruskal
时间复杂度为O(e*log(e)),适用于求边稀疏的network的mst。
算法思想:“等价类,并查集,边排序,选小边”。
代码如下,头文件添加:

typedef struct ...{
int v1;
int v2;
int cost;
int used;
}mst_kruskal_edge;源文件添加:
//get the class of i
int findparent(int *parent, int i)...{
while(parent[i] != -1)...{
i = parent[i];
}
return i;
}
//get the smallest edge that has not used
int getMin(mst_kruskal_edge *edge, int num)...{
int cost = INFINITY, index = -1;
for(int i = 0; i < num; i++)...{
if(edge[i].used == 0 && edge[i].cost < cost)...{
cost = edge[i].cost;
index = i;
}
}
return index;
}

/**//**
* the kruskal of mst
*/
void mst_kruskal(MGraph g)...{
//first construct the edge array
mst_kruskal_edge *edge = (mst_kruskal_edge *)
malloc(sizeof(mst_kruskal_edge) * g.vexnum / 2 * (g.vexnum - 1));
int i, j, k = 0;
for(i = 0; i < g.vexnum; i++)...{
for(j = i + 1; j < g.vexnum; j++)...{
if(g.arcs[i][j].adj > 0 && g.arcs[i][j].adj != INFINITY)...{
edge[k].v1 = i;
edge[k].v2 = j;
edge[k].cost = g.arcs[i][j].adj;
//this edge is not used
edge[k].used = 0;
k++;
}
}
}
printf("the num of edge is : %d ", k);
//the parent array, represent the class of the vertice
int *parent = (int *)malloc(sizeof(int) * g.vexnum);
//init it with -1
for(i = 0; i < g.vexnum; i++)...{
parent[i] = -1;
}
//construct the mst
printf("now constructing the mst... ");
for(i = 0; i < k; i++)...{
int index = getMin(edge, k);
if(index != -1)...{
int p1 = findparent(parent, edge[index].v1);
int p2 = findparent(parent, edge[index].v2);
if(p1 != p2)...{
printf("%c, %c, %d ",
g.vexs[edge[index].v1], g.vexs[edge[index].v2], edge[index].cost);
parent[p2] = p1;
}
edge[index].used = 1;
}else...{
break;
}
}
}

void main()...{
MGraph g;
createGragh(g);

/**//*
char start;
printf("input the start point of mst: ");
scanf("%c", &start);
mst_prim(g, start);
*/
mst_kruskal(g);
}程序的执行结果为:
please input the type of graph:
3
input the number of vertex:
6
input the name of vertex:
a
b
c
d
e
f
now constructing the matrix of graph...
0 6 1 5 10000 10000
6 0 5 10000 3 10000
1 5 0 5 6 4
5 10000 5 0 10000 2
10000 3 6 10000 0 6
10000 10000 4 2 6 0
the num of edge is : 10
now constructing the mst...
a, c, 1
d, f, 2
b, e, 3
c, f, 4
b, c, 5
Press any key to continue说明:kruskal至多对e条边各扫描一次,上面的查找算法的复杂度是O(e),所以实现的kruskal的复杂度是O(e*e)。但是如果使用堆排序,每次的查找复杂度可以变成O(log(e))(第一次需要O(e)来建立堆),从而Kruskal的复杂度是O(e * log(e))。

被折叠的 条评论
为什么被折叠?



