Prim算法
struct//辅助数组的定义,用来记录从顶点集U到V-U的权值最小的边
{
char adjvex;//最小的边在U中的那个顶点
int lowcost;//最小的边上的权值
}closedge[MVNum];
int Min(AMGraph G)//普里姆算法中的Min
{
int i,//次数
a,//用于记录最小值的位置
min = MaxInt;//先使min设为最大值
for(i=0;i<G.vexnum;i++)
{
if(closedge[i].lowcost == 0)
continue;
if(min>closedge[i].lowcost)
{
min = closedge[i].lowcost;
a = i;
}
}
return a;//返回最小值的位置
}
void MiniSpanTree_Prim(AMGraph G,char u)
{
int i,j,//记录次数变量
k;//顶点位置变量
for(j=0;j<G.vexnum;j++)//书上的函数LocateVex,为了简单直接写上了
{
if(G.vexs[j] == u)//找到输入的顶点b的位置
break;
}
k = j;//k为顶点u的下标
for(j=0;j<G.vexnum;j++)//对V-U的每一个顶点vj,初始化closedge[j]
{
if(j != k)
{
closedge[j].adjvex = u;
closedge[j].lowcost = G.arcs[k][j];
}
}
closedge[k].lowcost = 0;//初始,U={u},至此初始化结束
char u0,v0;
for(i=0;i<G.vexnum;i++)//选择其余n-1个顶点,生成n-1条边
{
k = Min(G);//求出closedge[]中除去已选边以外的最小边
u0 = closedge[k].adjvex;//u0为最小边的一个顶点,u0属于U
v0 = G.vexs[k];//v0为最小边的另一个顶点,v0属于V-U
printf("%c->%c ",u0,v0);//输出,当前的最小边(u0,v0)
closedge[k].lowcost = 0;//第k个顶点并入U集
for(j=0;j<G.vexnum;j++)
{
if(G.arcs[k][j]<closedge[j].lowcost)//新顶点并入U后重新选择最小边
{
closedge[j].adjvex = G.vexs[k];
closedge[j].lowcost = G.arcs[k][j];
}
}
}
}
Kruskal算法
int Vexset[MVNum];//再申请一个辅助数组Vexset
void Sort(AMGraph G)//书上的Sort函数,将数组Edege中的元素按权值从小到大排序,这里用 冒泡排序
{
int i,j;//记录次数
for(i=G.arcnum-1;i>=0;i--)//相邻两数的比较终点
{
for(j=0;j<i;j++)//进行相邻两数的比较
{
if(Edge[j].lowcoat > Edge[j+1].lowcoat)//如果大于,互换位置
{
Edge[G.arcnum] = Edge[j];
Edge[j] = Edge[j+1];
Edge[j+1] = Edge[G.arcnum];
}
}
}
}
int LocateVex(AMGraph G,char b)//定位函数,用于定位顶点b在顶点集的位置 并返回其位置
{
int j;
for(j=0;j<G.vexnum;j++)//利用循环找到和b相同的顶点
{
if(G.vexs[j] == b)//找到输入的顶点b的位置
break;
}
return j;//返回其位置j
}
void MiniSpanTree_Kruskal(AMGraph G)//无向网G以邻接矩阵形式存储,构造最小生成树,克鲁斯卡尔算法
{
int i,j;
Sort(G);//根据权值排序
for(i=0;i<G.vexnum;i++)//辅助数组,表示各顶点自成一个连通分量
Vexset[i] = i;
int v1,v2,
vs1,vs2;
for(i=0;i<G.arcnum;i++)//依次查看数组Edge中的边
{
v1 = LocateVex(G,Edge[i].Head);//v1为边的始点的下标 定位函数
v2 = LocateVex(G,Edge[i].Tail);//v2为边的终点的下标
vs1 = Vexset[v1];//获取边Edge[i]的始点所在的连通分量vs1
vs2 = Vexset[v2];//获取边Edge[i]的终点所在的连通分量vs2
if(vs1 != vs2)//边的两个顶点分属不同的连通分量
{
printf("%c->%c ",Edge[i].Head,Edge[i].Tail);//输出打印次边
for(j=0;j<G.vexnum;j++)//合并vs1和vs2两个分量,即两个集合统一编号
if(Vexset[j] == vs2)//集合编号为vs2的都改为vs1
Vexset[j] = vs1;
}
}
}