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; }
相关文章推荐
- HDU 2682 Tree 最小生成树 prim模板
- poj2421Constructing Roads-最小生成树prim
- 最小生成树 prim和kruskal算法
- HDU1102 - Constructing Roads 用优先队列优化Prim最小生成树
- HDU1102 最小生成树(已构造好部分边)Prim与Kruskal
- poj 1258 小白算法练习 Agri-Net 最小生成树 prim kruskal
- Luogu P1265修复公路【Prim最小生成树】By cellur925
- POJ 2253 Frogger (最小生成树.Prim)
- prim(最小生成树)
- 还是畅通工程(prim求最小生成树)
- 杭电3371 Connect the Cities(最小生成树 prim)
- POJ 1258 Prim最小生成树
- 最小生成树(Prim)代码实现
- POJ1789 Truck History(prim最小生成树)
- Poj(1251),Prim字符的最小生成树
- 最小生成树—Prim的实现
- Building a Space Station POJ 2031 【最小生成树 prim】
- 最小生成树算法:prim和kruskal
- 最小生成树_Prim
- 最小生成树算法Prim、Kruskal