#include <stdio.h>
#include <malloc.h>
//图的两种存储结构
#define INF 32767 //定义∞
#define MAXV 100 //最大顶点个数
typedef char InfoType;
//以下定义邻接矩阵类型
typedef struct
{
int no; //顶点编号
InfoType info; //顶点其他信息``
} VertexType; //顶点类型
typedef struct
{
int edges[MAXV][MAXV]; //邻接矩阵数组
int n, e; //顶点数,边数
VertexType vexs[MAXV]; //存放顶点信息
} MatGraph; //完整的图邻接矩阵类型
//以下定义邻接表类型
typedef struct ANode
{
int adjvex; //该边的邻接点编号
struct ANode *nextarc; //指向下一条边的指针
int weight; //该边的相关信息,如权值(用整型表示)
} ArcNode; //边节点类型
typedef struct Vnode
{
InfoType info; //顶点其他信息
int count; //存放顶点入度,仅仅用于拓扑排序
ArcNode *firstarc; //指向第一条边
} VNode; //邻接表头节点类型
typedef struct
{
VNode adjlist[MAXV]; //邻接表头节点数组
int n, e; //图中顶点数n和边数e
} AdjGraph; //完整的图邻接表类型
//------------------------------------------------------------
//----邻接矩阵的基本运算算法----------------------------------
//------------------------------------------------------------
void CreateMat(MatGraph &g, int A[MAXV][MAXV], int n, int e) //创建图的邻接矩阵
{
int i, j;
g.n = n; g.e = e;
for (i = 0; i < g.n; i++)
for (j = 0; j < g.n; j++)
g.edges[i][j] = A[i][j];
}
void DispMat(MatGraph g) //输出邻接矩阵g(实质输出一个二维数组)
{
int i, j;
for (i = 0; i < g.n; i++)
{
for (j = 0; j < g.n; j++)
if (g.edges[i][j] != INF)
printf("%4d", g.edges[i][j]);
else
printf("%4s", "∞");
printf("\n");
}
}
//------------------------------------------------------------
//------------------------------------------------------------
//----邻接表的基本运算算法------------------------------------
//------------------------------------------------------------
void CreateAdj(AdjGraph *&G, int A[MAXV][MAXV], int n, int e) //创建图的邻接表
{
int i, j;
ArcNode *p;
G = (AdjGraph *)malloc(sizeof(AdjGraph));
for (i = 0; i < n; i++) //给邻接表中所有头节点的指针域置初值
G->adjlist[i].firstarc = NULL;
for (i = 0; i < n; i++) //检查邻接矩阵中每个元素
for (j = n - 1; j >= 0; j--)
if (A[i][j] != 0 && A[i][j] != INF) //存在一条边
{
p = (ArcNode *)malloc(sizeof(ArcNode)); //创建一个节点p
p->adjvex = j;
p->weight = A[i][j];
p->nextarc = G->adjlist[i].firstarc; //采用头插法插入节点p
G->adjlist[i].firstarc = p;
}
G->n = n; G->e = n;
}
void DispAdj(AdjGraph *G) //输出邻接表G
{
ArcNode *p;
for (int i = 0; i < G->n; i++)
{
p = G->adjlist[i].firstarc;
printf("%3d: ", i);
while (p != NULL)
{
printf("%3d[%d]→", p->adjvex, p->weight);
p = p->nextarc;
}
printf("∧\n");
}
}
void DestroyAdj(AdjGraph *&G) //销毁图的邻接表
{
ArcNode *pre, *p;
for (int i = 0; i < G->n; i++) //扫描所有的单链表
{
pre = G->adjlist[i].firstarc; //p指向第i个单链表的首节点
if (pre != NULL)
{
p = pre->nextarc;
while (p != NULL) //释放第i个单链表的所有边节点
{
free(pre);
pre = p; p = p->nextarc;
}
free(pre);
}
}
free(G); //释放头节点数组
}
//------------------------------------------------------------
void Prim(MatGraph g, int v)
{
int lowcost[MAXV], min, n = g.n;
int closest[MAXV], i, j, k;
for (i = 0; i < n; i++) //给lowcost[]和closest[]置初值
{
lowcost[i] = g.edges[v][i];
closest[i] = v;
}
for (i = 1; i < n; i++) //找出n-1个顶点
{
min = INF;
for (j = 0; j < n; j++) //在(V-U)中找出离U最近的顶点k
if (lowcost[j] != 0 && lowcost[j] < min)
{
min = lowcost[j]; k = j;
}
printf(" 边(%d,%d)权为:%d\n", closest[k], k, min);
lowcost[k] = 0; //标记k已经加入U
for (j = 0; j < n; j++) //修改数组lowcost和closest
if (g.edges[k][j] != 0 && g.edges[k][j] < lowcost[j])
{
lowcost[j] = g.edges[k][j];
closest[j] = k;
}
}
}
int main()
{
int v = 3;
MatGraph g;
int A[MAXV][MAXV] = {
{0,5,8,7,INF,3},
{5,0,4,INF,INF,INF},
{8,4,0,5,INF,9},
{7,INF,5,0,5,6},
{INF,INF,INF,5,0,1},
{3,INF,9,6,1,0} };
int n = 6, e = 10;
CreateMat(g, A, n, e); //建立图8.10的邻接矩阵
printf("图G的邻接矩阵:\n"); DispMat(g);
printf("普里姆算法求解结果:\n");
Prim(g, 0);
return 1;
}
求最小生成树——普里姆算法
最新推荐文章于 2023-11-07 09:24:35 发布