您的位置:首页 > 编程语言 > C语言/C++

Prim最小生成树

2016-09-15 15:22 225 查看


1. 静态的示意

  由N个顶点的无向连通图生成最小生成树的各条边放在容量为N - 1的数组中。

#include <stdio.h>
#include <stdlib.h>
#define N 6//N个顶点
struct Edge {int i; int j; int w;};//i: 起点下标 j: 终点下标 w: 权

//int (*adjmatrix)
: 邻接矩阵行地址
//Edge edge[N - 1]: 输出边表
void PrimMST(const int (*adjmatrix)
, Edge edge[N - 1])
{
int edge_count = 0;//当前输出边表元素个数
int vex
= {};//存放已加入的顶点下标
int vex_count = 0;//已加入的顶点个数
bool joint
= {};//i号点是否加入顶点表,默认未加入
int shortest = INT_MAX;//最短边长
Edge first_edge;
for (int i = 0; i < N; i++)//寻找初始最短边
{
for (int j = i; j < N; j++)//因为是无向图只考虑上三角
{
if (adjmatrix[i][j] < shortest)
{
first_edge.i = i;
first_edge.j = j;
first_edge.w = adjmatrix[i][j];
shortest = adjmatrix[i][j];
}
}
}
edge[edge_count++] = first_edge;//边表首元素
vex[vex_count++] = first_edge.i;//顶点表首元素
vex[vex_count++] = first_edge.j;//此时顶点表2个元素
joint[first_edge.i] = true;
joint[first_edge.j] = true;
while (edge_count < N - 1)
{
//补集中找最短边
shortest = INT_MAX;
//save_i, save_j用于存放找到的最近点形成的边所构成的线段端点下标
int save_i;
int save_j;
for (int i = 0; i < vex_count; i++)//点表中
{
for (int j = 0; j < N; j++)
{
if (!joint[j] && adjmatrix[vex[i]][j] < shortest)//没有加入顶点表且权最小
{
shortest = adjmatrix[vex[i]][j];
save_i = vex[i];
save_j = j;
}
}
}
joint[save_j] = true;//标记save_j
vex[vex_count++] = save_j;//顶点表中加入save_j点号
edge[edge_count].i = save_i;
edge[edge_count].j = save_j;
edge[edge_count].w = adjmatrix[save_i][save_j];
edge_count++;
}
}

int main()
{
int adjmatrix

=
{
INT_MAX, 6, 1, 5, INT_MAX, INT_MAX,
6, INT_MAX, 5, INT_MAX, 3, INT_MAX,
1, 5, INT_MAX, 5, 6, 4,
5, INT_MAX, 5, INT_MAX, INT_MAX, 2,
INT_MAX, 3, 6, INT_MAX, INT_MAX, 6,
INT_MAX, INT_MAX, 4, 2, 6, INT_MAX
};//N * N邻接矩阵

Edge e[N - 1];//存放输出结果的边表
PrimMST(adjmatrix, e);//测试静态情况下的函数
for (int i = 0; i < N - 1; i++)
{
printf("p%d = %d, p%d = %d, w%d%d = %d\n", i + 1, e[i].i + 1, i + 2, e[i].j + 1, i + 1, i + 2, e[i].w);
}

return 0;
}


2. 实际使用会用到给定长度的邻接矩阵(动态分配的)
#include <stdio.h>
#include <stdlib.h>
#define N 6//N个顶点
struct Edge {int i; int j; int w;};//i: 起点下标 j: 终点下标 w: 权

//对动态分配的邻接矩阵生成最小生成树
//int ** adjmatrix: 动态分配的邻接矩阵
//int n: 顶点个数
//Edge * edge: 存放n - 1条边的数组
void PrimMSTDynamic(int ** adjmatrix, int n, Edge * edge)
{
int edge_count = 0;//当前输出边表元素个数
int * vex = (int *)malloc(n * sizeof(int));//存放已加入的顶点下标
int vex_count = 0;//已加入的顶点个数
bool * joint = (bool *)malloc(n * sizeof(bool));//i号点是否加入顶点表,默认未加入
for (int i = 0; i < n; i++)
joint[i] = false;
int shortest = INT_MAX;//最短边长
Edge first_edge;
for (int i = 0; i < n; i++)//寻找初始最短边
{
for (int j = i; j < n; j++)//因为是无向图只考虑上三角
{
if (adjmatrix[i][j] < shortest)
{
first_edge.i = i;
first_edge.j = j;
first_edge.w = adjmatrix[i][j];
shortest = adjmatrix[i][j];
}
}
}
edge[edge_count++] = first_edge;//边表首元素
vex[vex_count++] = first_edge.i;//顶点表首元素
vex[vex_count++] = first_edge.j;//此时顶点表2个元素
joint[first_edge.i] = true;
joint[first_edge.j] = true;
while (edge_count < n - 1)
{
//补集中找最短边
shortest = INT_MAX;
//save_i, save_j用于存放找到的最近点形成的边所构成的线段端点下标
int save_i;
int save_j;
for (int i = 0; i < vex_count; i++)//点表中
{
for (int j = 0; j < n; j++)
{
if (!joint[j] && adjmatrix[vex[i]][j] < shortest)//没有加入顶点表且权最小
{
shortest = adjmatrix[vex[i]][j];
save_i = vex[i];
save_j = j;
}
}
}
joint[save_j] = true;//标记save_j
vex[vex_count++] = save_j;//顶点表中加入save_j点号
edge[edge_count].i = save_i;
edge[edge_count].j = save_j;
edge[edge_count].w = adjmatrix[save_i][save_j];
edge_count++;
}
free(vex);
free(joint);
}

int main()
{
int adjmatrix

=
{
INT_MAX, 6, 1, 5, INT_MAX, INT_MAX,
6, INT_MAX, 5, INT_MAX, 3, INT_MAX,
1, 5, INT_MAX, 5, 6, 4,
5, INT_MAX, 5, INT_MAX, INT_MAX, 2,
INT_MAX, 3, 6, INT_MAX, INT_MAX, 6,
INT_MAX, INT_MAX, 4, 2, 6, INT_MAX
};//N * N邻接矩阵

//开辟
int n = 6;
int ** adjmatrix_dynamic = (int **)malloc(n * sizeof(int *));
for (int i = 0; i < n; i++)
{
adjmatrix_dynamic[i] = (int *)malloc(n * sizeof(int));
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
adjmatrix_dynamic[i][j] = adjmatrix[i][j];
}
}

Edge * e_dynamic = (Edge *)malloc((n - 1) * sizeof(Edge));
PrimMSTDynamic(adjmatrix_dynamic, n, e_dynamic);//测试动态情况下的函数
for (int i = 0; i < n - 1; i++)
{
printf("p%d = %d, p%d = %d, w%d%d = %d\n", i + 1, e_dynamic[i].i + 1, i + 2, e_dynamic[i].j + 1, i + 1, i + 2, e_dynamic[i].w);
}

//回收
for (int i = 0; i < n; i++)
{
free(adjmatrix_dynamic[i]);
}
free(adjmatrix_dynamic);
free(e_dynamic);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 prim