用c语言写出用邻接矩阵作为图的存储结构建立一个网,并构造该网的最小生成树
时间: 2024-03-16 16:44:58 浏览: 62
基于邻接矩阵存储的图的最小生成树的Prime算法
好的,我会尽力回答你的问题。
首先,我们需要定义一个结构体来表示图的存储结构,包含顶点数和邻接矩阵。
```c
#define MAXVEX 100 // 最大顶点数
typedef struct {
char vexs[MAXVEX]; // 存储顶点信息
int arc[MAXVEX][MAXVEX]; // 存储邻接矩阵
int vexnum; // 顶点数
} MGraph;
```
接着,我们需要定义一个函数来创建一个网,输入顶点数和边数,以及每条边的权值,构造邻接矩阵表示的图。
```c
void createMGraph(MGraph *G)
{
int i, j, k, w;
printf("请输入顶点数和边数:");
scanf("%d%d", &G->vexnum, &k);
getchar(); // 吃掉回车符
printf("请输入顶点信息:\n");
for (i = 0; i < G->vexnum; i++) {
printf("第%d个顶点:", i + 1);
scanf("%c", &G->vexs[i]);
getchar(); // 吃掉回车符
}
// 初始化邻接矩阵
for (i = 0; i < G->vexnum; i++) {
for (j = 0; j < G->vexnum; j++) {
G->arc[i][j] = INT_MAX; // 初始权值为无穷大
}
}
// 构造邻接矩阵
for (i = 0; i < k; i++) {
char v1, v2;
printf("请输入第%d条边的两个顶点和权值:", i + 1);
scanf("%c%c%d", &v1, &v2, &w);
getchar(); // 吃掉回车符
int m = locateVex(*G, v1);
int n = locateVex(*G, v2);
G->arc[m][n] = G->arc[n][m] = w; // 无向图
}
}
```
其中,`locateVex` 函数用于在图中查找指定顶点的位置。
```c
int locateVex(MGraph G, char ch)
{
int i;
for (i = 0; i < G.vexnum; i++) {
if (G.vexs[i] == ch) {
return i;
}
}
return -1;
}
```
接下来,我们需要定义一个结构体来表示边的信息,包括起点、终点和权值。
```c
typedef struct {
char start; // 边的起点
char end; // 边的终点
int weight; // 边的权值
} Edge;
```
然后,我们需要定义一个函数来从邻接矩阵表示的图中提取所有的边,并按权值从小到大排序。
```c
void getEdges(MGraph G, Edge *edges)
{
int i, j, k = 0;
for (i = 0; i < G.vexnum; i++) {
for (j = i + 1; j < G.vexnum; j++) {
if (G.arc[i][j] != INT_MAX) { // 存在边
edges[k].start = G.vexs[i];
edges[k].end = G.vexs[j];
edges[k].weight = G.arc[i][j];
k++;
}
}
}
// 按权值从小到大排序
qsort(edges, k, sizeof(Edge), cmp);
}
```
其中,`cmp` 函数用于比较两条边的权值大小。
```c
int cmp(const void *a, const void *b)
{
Edge *e1 = (Edge *)a;
Edge *e2 = (Edge *)b;
return e1->weight - e2->weight;
}
```
最后,我们需要定义一个函数来构造邻接矩阵表示的图的最小生成树。我们采用 Kruskal 算法,即按权值从小到大选择边,如果这条边的两个顶点不在同一个连通分量中,则将其加入最小生成树中。
```c
void miniSpanTree_Kruskal(MGraph G)
{
int i, j;
Edge edges[MAXVEX * (MAXVEX - 1) / 2]; // 存储所有边
getEdges(G, edges); // 提取所有边
int parent[MAXVEX]; // 记录每个顶点所在的连通分量
for (i = 0; i < G.vexnum; i++) {
parent[i] = i;
}
int count = 0; // 记录已选择的边数
int k = 0; // 记录当前考虑的边
Edge result[MAXVEX]; // 存储最小生成树的边
while (count < G.vexnum - 1) { // 已选择的边数为顶点数减一
Edge e = edges[k++]; // 选择当前考虑的边
int m = locateVex(G, e.start);
int n = locateVex(G, e.end);
int pm = find(parent, m); // 查找起点所在的连通分量
int pn = find(parent, n); // 查找终点所在的连通分量
if (pm != pn) { // 不在同一个连通分量中
parent[pm] = pn; // 合并连通分量
result[count++] = e; // 加入最小生成树
}
}
printf("最小生成树的边为:\n");
for (i = 0; i < count; i++) {
printf("%c-%c %d\n", result[i].start, result[i].end, result[i].weight);
}
}
int find(int *parent, int f)
{
while (f != parent[f]) {
f = parent[f];
}
return f;
}
```
这样,我们就完成了用邻接矩阵作为图的存储结构建立一个网,并构造该网的最小生成树的 C 语言代码。
阅读全文