#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INFINITY 30000 //定义一个权值的最大值
#define MAX_VERTEX_NUM 20 // 图的最大顶点数
typedef struct
{
int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 邻接矩阵
int vexnum,arcnum; // 图的当前顶点和边数
}Graph;
typedef struct
{
int adjvex; // 某顶点与已构造好的部分生成树的顶点之间权值最小 的'顶点'
int lowcost; // 某顶点与已构造好的部分生成树的顶点之间的最小权值
}ClosEdge[MAX_VERTEX_NUM]; // 用普里姆算法求最小生成树时的辅助数组
int min( ClosEdge closedge, int vexnum );
void CreateGraph(Graph *G);
void MiniSpanTree_PRIM(Graph *G,int u);
//==================================================
int main()
{
// freopen( "in.txt", "r", stdin );
Graph G; //采用邻接矩阵结构的图
char j = 'y';
int u;
printf("prim 算法构造最小生成树,严格按照严蔚敏书上实现\n");
printf("首先输入图的顶点数和弧数.\n格式:顶点数,弧数;例如:4,4\n");
printf("接着输入各条弧(弧尾,弧头)和弧的权值。\n");
printf("格式:弧尾,弧头,权值;例如\n1,2,1\n1,3,2\n2,4,3\n3,4,4\n");
printf("程序将会构造该图的最小代价生成树。\n");
printf("并显示该最小生成树。\n1,2\n1,3\n2,4\n");
while(j != 'N' && j!='n' )
{
CreateGraph( &G ); /* 生成邻接矩阵结构的图 */
printf("从哪一顶点开始:");
scanf( "%d", &u ); /* 输入普里姆算法中的起始顶点 */
MiniSpanTree_PRIM( &G, u ); /* 普里姆算法求最小生成树 */
printf("最小代价生成树构造完毕,继续进行吗?(Y/N)");
fflush(stdin); /*清除缓冲区*/
scanf(" %c",&j);
}
return 0;
}
void CreateGraph(Graph *G )
{
/* 构造邻接矩阵结构的图G */
int i,j;
int start,end,weight;
printf("请输入图的顶点数和弧数:");
scanf( "%d,%d", &G->vexnum, &G->arcnum ); /* 输入图的顶点数和边数 */
for( i=1; i <= G->vexnum; i++ )
for( j=1; j<=G->vexnum; j++ )
G->arcs[i][j] = INFINITY; /* 初始化邻接矩阵 */
printf("输入弧和其权值,格式:弧尾,弧头,权值\n");
for( i=1; i <= G->arcnum; i++ )
{
scanf( "%d,%d,%d", &start, &end, &weight ); /* 输入边的起点和终点及权值 */
G->arcs[start][end] = weight;
G->arcs[end][start] = weight;
}
/*调试代码
for( i=1; i <= G->vexnum; i++ )
{
for( j=1; j<=G->vexnum; j++ )
printf( "%d\t", G->arcs[i][j] );
printf( "\n" );
}
*/
}
void MiniSpanTree_PRIM(Graph *G,int u)
{
/* 从第u个顶点出发构造图G的最小生成树 */
ClosEdge closedge;
int i,j,k,w;
printf("最小代价生成树:\n");
for( j=1;j <= G->vexnum; j++ ) /* 辅助数组初始化 */
if( j != u )
{
closedge[j].adjvex = u;
closedge[j].lowcost = G->arcs[u][j];
}
closedge[u].lowcost=0; /* 初始,U={u} */
for( i=1; i < G->vexnum; i++ ) /* 选择其余的(G->vexnum) - 1个顶点 */
{
/*调试代码
printf( "权值" );
for( w = 1; w <= G->vexnum; w++ )
printf( "%d ", closedge[w].lowcost );
printf( "\n" );
*/
k = min(closedge, G->vexnum); //求出生成树的下一个顶点
printf("%d,%d\n", closedge[k].adjvex, k ); // 输出生成树的边
closedge[k].lowcost=0; //第k顶点并入U集
for(j=1; j <= G->vexnum; j++) /* 新顶点并入U后,修改辅助数组*/
if( G->arcs[k][j] < closedge[j].lowcost )//更新过程
{ //如果新并入的点和U-V的权值小于和原点集V和U-V的权值,这更新数组,采用更小的权值
closedge[j].adjvex = k;
closedge[j].lowcost = G->arcs[k][j];
}
/* 调试代码
printf( "权值" );
for( w = 1; w <= G->vexnum; w++ )
printf( "%d ", closedge[w].lowcost );
printf( "\n" );
*/
}
}
/* 在辅助数组closedge[vexnum]中选择权值最小的顶点,并返回其位置 */
int min( ClosEdge closedge, int vexnum )
{
int i;
int w,p;
w=INFINITY;
for( i=1; i <= vexnum; i++ )
if( closedge[i].lowcost != 0 && closedge[i].lowcost < w )
{
w = closedge[i].lowcost;
p=i;
}
return p;
}
最小生成树prim算法
最新推荐文章于 2022-07-24 18:04:53 发布