一、prim算法;
int Prim(MGraph Graph,LGraph MST)
{
//将最小生成树保存为邻接表存储的图MST,返回最小权重
WeightType dist[MaxVertexNum],TotalWeight;
Vertex parent[MaxVertexNum],V,W;
int VCount;
Edge E;
//初始化
for(V=0;V<Graph->Nv ;V++){
//假设V到W没有直接的边
dist[V]=Graph->G[0][V];
parent[V]=0;
}
TotalWeight=0;//初始化权重和
VCount=0;//初始化收录的权重和
//创建包含所有顶点但没有变的图(邻接表)
MST=CreateLGraph(Graph->Nv);
E=(Edge) malloc(sizeof(struct ENode));
//将初始点0收录进MST
dist[0]=0;
VCount++;
parent[0]=-1;//当前树根是0
while(1){
//寻找未被收录顶点中dist最小者
V=FindMinDist(Graph,dist);
if(V==ERROR)
break;
//将V及相应的边<parent[V],V>收录进MST
E->V1 =parent[V];
E->V2 =V;
E->Weight =dist[V];
InsertLEdge(MST,E);
TotalWeight+=dist[V];
dist[V]=0;
VCount++;
//判断是否可以缩短路径
for(W=0;W<Graph->Nv ;W++)
if(dist[W]!=0&&Graph->G[V][W]<INFINITY){
//W是V的邻接点并且未被收录
if(Graph->G[V][W]<dist[W]){
//收录V使dist[V]变小
dist[W]=Graph->G[V][W];
parent[W]=V;
}
}
} //while结束
if(VCount<Graph->Nv )
TotalWeight=ERROR;//MST中收录的顶点不到V
return TotalWeight;
}
二、完整代码:
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define MaxVertexNum 100 //最大顶点数
#define INFINITY 65535 //∞设为双字节无符号整型的最大值65535
#define ERROR -1//错误标记,表示生成树不存在
typedef int Vertex; //用顶点下标表示顶点,为整型
typedef int WeightType; //边的权值设为整型
typedef char DataType; //顶点存储的数据类型为字符型
//邻接矩阵
/*-----------图的定义-------------*/
typedef struct GNode *PtrToGNode;
struct GNode{
int Nv;//顶点数
int Ne; //边数
WeightType G[MaxVertexNum][MaxVertexNum]; //邻接矩阵
DataType Data[MaxVertexNum];//存顶点的数据
};
typedef PtrToGNode MGraph; //以邻接矩阵存储的图的类型
/*-----------边的定义-------------*/
typedef struct ENode *PtrToENode;
struct ENode{
Vertex V1,V2;//有向边<V1,V2>
WeightType Weight; //权值
};
typedef PtrToENode Edge;
//邻接表
/*-----------邻接点的定义-------------*/
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode{
Vertex AdjV;//邻接点下标
WeightType Weight;//边的权值
PtrToAdjVNode Next;//指向下一个邻接点
};
/*-----------顶点表头结点的定义-------------*/
typedef struct VNode{
PtrToAdjVNode FirstEdge;//边表头指针
DataType Data;//存顶点的数据
}AdjList[MaxVertexNum];//AdjList是邻接表类型
/*-----------图结点的定义-------------*/
typedef struct LGNode *LGraph;
struct LGNode{
int Nv;//顶点数
int Ne;//边数
AdjList G;//邻接表
};
/*-----------创建邻接矩阵-------------*/
MGraph CreateGraph(int VertexNum)
{//创建一个包含全部顶点的无边图
Vertex V,W;
MGraph Graph;
Graph=(MGraph)malloc(sizeof(struct GNode));
Graph->Nv =VertexNum;
Graph->Ne =0;
//初始化邻接矩阵
//顶点编号从0-Graph->Nv-1
for(V=0;V<Graph->Nv;V++)
for(W=0;W<Graph->Nv;W++)
Graph->G[V][W]=INFINITY;//都为∞
// PrintResult(Graph);
return Graph;
}
/*-----------创建邻接表-------------*/
LGraph CreateLGraph(int VertexNum)
{
//初始化一个只有顶点没有边的图
LGraph Graph;
Vertex V;
Graph=(LGraph)malloc(sizeof(struct LGNode));
Graph->Nv =VertexNum;
Graph->Ne =0;
//初始化邻接表头指针
for(V=0;V<Graph->Nv ;V++)
Graph->G[V].FirstEdge =NULL;
return Graph;
}
/*-----------插入邻接矩阵-------------*/
void InsertEdge(MGraph Graph,Edge E)
{//逐条插入边
//插入边<V1,V2>
Graph->G [E->V1 ][E->V2 ]=E->Weight ;
//若是无向图,还需要插入边<V2,V1>
Graph->G [E->V2 ][E->V1 ]=E->Weight ;
}
/*-----------插入邻接表-------------*/
void InsertLEdge(LGraph Graph,Edge E)
{
//逐条加入边
PtrToAdjVNode NewNode;
//插入边<V1,V2>,为V2建立新的连接点
NewNode =(PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV =E->V2 ;
NewNode->Weight =E->Weight ;
//将V2插入V1的表头
NewNode->Next =Graph->G[E->V1 ].FirstEdge;
Graph->G[E->V1 ].FirstEdge =NewNode;
//若是无向图,插入边<V2,V1>
NewNode=(PtrToAdjVNode) malloc(sizeof(struct AdjVNode));
NewNode->AdjV =E->V1 ;
NewNode->Weight =E->Weight ;
// 将V1插入V2的表头
NewNode->Next =Graph->G[E->V2 ].FirstEdge ;
Graph->G[E->V2 ].FirstEdge =NewNode;
}
/*-----------读入数据创建图-------------*/
MGraph BuildGraph()
{
MGraph Graph;
Edge E;
Vertex V;
int Nv,i;
printf("请输入图的顶点数:");
scanf("%d",&Nv);
Graph=CreateGraph(Nv);//初始化有Nv个顶点但没有边的图
printf("请输入边的个数:");
scanf("%d",&(Graph->Ne));
if(Graph->Ne !=0){//有边
//插入边的起点,终点,权值
printf("请输入%d个边的起点 终点 权值:\n",Graph->Ne );
E=(Edge)malloc(sizeof(struct ENode));//开辟空间
for(i=0;i<Graph->Ne ;i++){
printf("%d : ",i);
scanf("%d %d %d",&E->V1,&E->V2 ,&E->Weight );
InsertEdge(Graph,E);
}
}
//如果顶点有数据的话,读入数据
//for(V=0;V<Graph->Nv ;V++)
// scanf("%c",&(Graph->Data[V]));
return Graph;
}
/*---------------寻找最小dist权值----------------*/
Vertex FindMinDist(MGraph Graph,WeightType dist[])
{
Vertex MinV,V;
WeightType MinDist=INFINITY;
for(V=0;V<Graph->Nv ;V++){
if(dist[V]!=0&&dist[V]<MinDist){
MinDist=dist[V];
MinV=V;//更新对应点
}
}
if(MinDist<INFINITY)//找到最小dist
return MinV;//返回对应的下标
else return ERROR;//不存在
}
/*----------------prim算法----------------*/
int Prim(MGraph Graph,LGraph MST)
{
//将最小生成树保存为邻接表存储的图MST,返回最小权重
WeightType dist[MaxVertexNum],TotalWeight;
Vertex parent[MaxVertexNum],V,W;
int VCount;
Edge E;
//初始化
for(V=0;V<Graph->Nv ;V++){
//假设V到W没有直接的边
dist[V]=Graph->G[0][V];
parent[V]=0;
}
TotalWeight=0;//初始化权重和
VCount=0;//初始化收录的权重和
//创建包含所有顶点但没有变的图(邻接表)
MST=CreateLGraph(Graph->Nv);
E=(Edge) malloc(sizeof(struct ENode));
//将初始点0收录进MST
dist[0]=0;
VCount++;
parent[0]=-1;//当前树根是0
while(1){
//寻找未被收录顶点中dist最小者
V=FindMinDist(Graph,dist);
if(V==ERROR)
break;
//将V及相应的边<parent[V],V>收录进MST
E->V1 =parent[V];
E->V2 =V;
E->Weight =dist[V];
InsertLEdge(MST,E);
TotalWeight+=dist[V];
dist[V]=0;
VCount++;
//判断是否可以缩短路径
for(W=0;W<Graph->Nv ;W++)
if(dist[W]!=0&&Graph->G[V][W]<INFINITY){
//W是V的邻接点并且未被收录
if(Graph->G[V][W]<dist[W]){
//收录V使dist[V]变小
dist[W]=Graph->G[V][W];
parent[W]=V;
}
}
} //while结束
if(VCount<Graph->Nv )
TotalWeight=ERROR;//MST中收录的顶点不到V
return TotalWeight;
}
void PrintResult(MGraph Graph)
{
printf("邻接矩阵:\n");
int V,W;
for(V=0;V<Graph->Nv ;V++){
for(W=0;W<Graph->Nv ;W++){
if(Graph->G[V][W]==INFINITY)printf("∞ ");
else printf("%d ",Graph->G[V][W]);
}
printf("\n");
}
}
int main()
{
MGraph Graph;
LGraph MST;
Graph=BuildGraph();
PrintResult(Graph);
int TotalWeight=Prim(Graph,MST);
printf("TotalWeight=%d\n",TotalWeight);
return 0;
}
三、运行: