采用邻接矩阵的存储结构构建无向网,然后用Prim和Kruskal算法求出最小生成树。
总代码:
#include <stdio.h>
#include <stdlib.h>
#define VRType int//在这里是权值类型
#define MAX_VERTEX_NUM 10//最大顶点个数
#define VertexType char //顶点类型
#define INFINITY 32767 //无穷大,不连通
//边的结构
typedef struct ArcCell{
VRType adj;//权值
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
//图的结构
typedef struct {
VertexType vexs[MAX_VERTEX_NUM];//顶点向量
AdjMatrix arcs;//邻接矩阵
int vexnum,arcnum;//顶点数,边数
}MGraph;
//辅助数组,记录从U到V-U的最小代价的边
typedef struct {
VertexType adjvex;
VRType lowcost;
}Closedge;
//
typedef struct edge{
int begin;//起始顶点位置
int end;//终点位置
VRType weight;//权重
}Edge[100];
//函数声明
void CreateMGraph(MGraph &G);
void Prim(MGraph G,VertexType v);
void Kruskal(MGraph G);
int LocateVex(MGraph G,VertexType v);
int main(){
int i=1;
MGraph G;
VertexType v;
while(i){
printf("第%d个图:\n",i++);
CreateMGraph(G);
//Prim算法
printf("========Prim算法========:\n输入从哪个顶点开始构造:");
fflush(stdin);
scanf("%c",&v);
Prim(G,v);
//Kruskal算法
printf("\n========Kruskal算法========:\n");
Kruskal(G);
system("pause");
}
return 0;
}
//函数实现
int minimum(Closedge *closedge,MGraph G){
int i=0,j,k,min;
while(!closedge[i].lowcost){//找到第一个权值不为零的
i++;
}
min = closedge[i].lowcost;
k = i;
for(j=i+1;j<G.vexnum;j++){
if(closedge[j].lowcost >0 && min >closedge[j].lowcost){
min = closedge[j].lowcost;
k = j;
}
}
return k;
}
void Prim(MGraph G,VertexType v){
int k = LocateVex(G,v),i=0,j=0;
Closedge closedge[MAX_VERTEX_NUM];
//辅助矩阵初始化
for(i=0;i<G.vexnum;i++){
closedge[i].adjvex = v;
closedge[i].lowcost = G.arcs[k][i].adj;
// printf("==%d\n",closedge[i].lowcost);
}
closedge[k].lowcost = 0;//把结点v加入集合U中
for(i=1;i<G.vexnum;i++){
k = minimum(closedge,G) ;//求出最小生成树的下一个节点,第k顶点
printf("%c--->%c\n",closedge[k].adjvex,G.vexs[k]);
closedge[k].lowcost = 0;//第k结点加入U
//重新选择最小边
for(j=0;j<G.vexnum;j++){
if( G.arcs[k][j].adj < closedge[j].lowcost){
closedge[j].adjvex = G.vexs[k];
closedge[j].lowcost = G.arcs[k][j].adj;
}
}
}
}
//打印边数组
void print(Edge *E,int n,MGraph G){
for(int i=0;i<n;i++){
printf("%c---%c---%d\n",G.vexs[E[i]->begin],G.vexs[E[i]->end],G.arcs[E[i]->begin][E[i]->end].adj);
}
}
//按权值从小到大排序
int cmp(const void *a,const void *b){
return ((struct edge*)a)->weight - ((struct edge*)b)->weight;
}
void Kruskal(MGraph G){
Edge *E = (Edge*)malloc(sizeof(Edge)*G.arcnum*2) ;
int i=0,j=0,k=0;
for(i=0;i<G.vexnum;i++){
for(j=0;j<G.vexnum;j++){
if(G.arcs[i][j].adj != INFINITY){
E[k]->begin = i;
E[k]->end = j;
E[k]->weight = G.arcs[i][j].adj;
k++;
}
}
}
qsort(E,k,sizeof(E[0]),cmp);
print(E,k,G);
int *vset = (int *)malloc(sizeof(int)*G.vexnum);
for (i=0;i<G.vexnum;i++){ //初始化辅助数组
vset[i]=i;
}
k=1; //生成的边数,最后要刚好为总边数
j=0; //E中的下标
while (k<G.vexnum){
int set1 = vset[E[j]->begin];
int set2 = vset[E[j]->end]; //得到两顶点属于的集合
if (set1!=set2){ //不在同一集合内的话,把边加入最小生成树
printf("%c--->%c weight = %d\n",G.vexs[E[j]->begin],G.vexs[E[j]->end],E[j]->weight);
k++;
for (i=0;i<G.vexnum;i++)
{
if (vset[i]==set2)
{
vset[i]=set1; //避免重复添加,像A-B添加后B-A又添加
}
}
}
j++;
}
free(vset);
free(E);
}
void CreateMGraph(MGraph &G){
printf("输入顶点数,边数:");
scanf("%d %d",&G.vexnum,&G.arcnum);
int i=0,j=0;
for(i=0;i<G.vexnum;i++){
printf("输入第%d个顶点编号:",i+1);
fflush(stdin);
scanf("%c",&G.vexs[i]);
}
//初始化矩阵
for(i=0;i<G.vexnum;i++){
for(j=0;j<G.vexnum;j++){
G.arcs[i][j].adj = INFINITY;
}
}
char v1,v2;
int w;
for(int k=0;k<G.arcnum;k++){
printf("输入顶点1,顶点2及其权值:");
fflush(stdin);
scanf("%c %c %d",&v1,&v2,&w);
i = LocateVex(G,v1);
j = LocateVex(G,v2);
G.arcs[i][j].adj = w;
G.arcs[j][i] = G.arcs[i][j];//对称边
// printf("%d\n",G.arcs[j][i].adj);
}
}
int LocateVex(MGraph G,VertexType v){
for(int i=0;i<G.vexnum;i++){
if(v == G.vexs[i]){
return i;
}
}
return -1;
}