最小生成树prim算法实现
‘ ’最小生成树,就是权值(两点间直线的值)之和的最小值。
首先,要用二维数组记录点和权值。如上图所示无向图:
int G[6][6];
G[1][2]= G[2][1]=4;
G[1][3]= G[3][1]=2;
......
然后再求最小生成树。具体方法是:
1.先选取一个点作起始点,然后选择它邻近的权值最小的点(如果有多个与其相连的相同最小权值的点,随便选取一个)。如1作为起点。
使用全局变量来用做标记 visited[1]=1;
pos=1;
//用low[]数组不断刷新最小权值,low[i](0<i<=点数)的值为:i点到邻近点(未被标记)的最小距离。
low[1]=0; //起始点i到邻近点的最小距离为0
low[2]=map[pos][2]=4;
low[3]=map[pos][3]=2;
low[4]==map[pos][4]=3;
low[5]=map[pos][5]=MaxInt; //无法直达
low[6]=map[pos][6]=MaxInt;
2.再在伸延的点找与它邻近的两者权值最小的点。
//low[]以3作当前位置进行更新
visited[3]=1;
pos=3;
low[1]=0; //已标记,不更新
low[2]=map[1][2]=4; //比5小,不更新
low[3]=2; //已标记,不更新
low[4]=map[1][4]=3; //比1大,更新后为:low[4]=map[3][4]=1;
low[5]=map[1][5]=MaxInt; //无法直达,不更新
low[6]=map[1][6]=MaxInt; //比2大,更新后为:low[6]=map[3][6]=2;
-----------------------------------------------------------------------------------------------------------------------------------------------
是最小值而又没有被标记的为low[4]
visited[4]=1;
pos=4;
low[1]=0; //已标记不更新
low[2]=map[1][2]=4; //map[4][2] == 4 一样大不更新
low[3]=2; //已标记不更新
low[4]=map[1][4]=1; //已标记不更新
low[5]=map[4][5]=6; //比max小更新
low[6]=map[4][6]=2; //和map[3][6]一样大不更新
-------------------------------------------------------------------------------------------------------------------------------------------------
是最小值而又没有被标记的为low[6]
visited[2]=1;
pos=4;
low[1]=0; //已标记不更新
low[2]=map[1][2]=4; //已标记不更新
low[3]=2; //已标记不更新
low[4]=map[1][4]=1; //已标记不更新
low[5]=map[6][5]=4; //比map[4][5]小更新为3
low[6]=map[4][6]=2; //已标记不更新
--------------------------------------------------------------------------------------------------------------------------------------
是最小值而又没有被标记的为low[2]
visited[4]=1;
pos=4;
low[1]=0; //已标记不更新
low[2]=map[1][2]=4; //比它大不更新
low[3]=2; //已标记不更新
low[4]=map[1][4]=1; //已标记不更新
low[5]=map[2][5]=3; //比他小更新
low[6]=map[4][6]=2; //已标记不更新
----------------------------------------------------------------------------------------------------------------------------------------------
是最小值而又没有被标记的为low[5]
visited[4]=1;
pos=4;
low[1]=0; //已标记不更新
low[2]=map[1][2]=4; //已标记不更新
low[3]=2; //已标记不更新
low[4]=map[1][4]=1; //已标记不更新
low[5]=map[6][5]=4; //已标记不更新
low[6]=map[4][6]=2; //已标记不更新
------------------------------------------------------------------------------------------------------------------------------------------------
3.如此类推...
所有权值相加就是最小生成树,其值为2+1+2+4+3=12。
--------------------------------------------------------------------------------------------------------------------------------------------
#include <cstdio> #include <cstdlib> //#define _OJ_ #define max 999 int visit[100]; typedef struct Graph1 { int nv; int ne; int G[100][100]; } Graph1, *Graph; int prim_Graph(Graph g) { int i, j, i1, pos, result, min; int low[100]; visit[1] = 1; low[1] = 0; result = 0; pos = 1;//从第一个开始 for(i = 2;i <= g->nv; i++) { low[i] = g->G[pos][i]; printf("low%d == %d ", i, low[i]);} printf(" "); for(i = 1;i < g->nv; i++) { min = max; for(j = 1;j <= g->nv; j++) { if(visit[j] == 0 && min > low[j]) { min = low[j]; pos = j; } } result += min; visit[pos] = 1; printf("pos == %d ", pos); for(i1 = 1;i1 <= g->nv; i1++) { if(visit[i1] == 0 && low[i1] > g->G[pos][i1]) low[i1] = g->G[pos][i1]; //把没有访问过的与pos相邻的且权 //重比原来小的就更改,否则保持原来最小的值 printf("low%d == %d ", i1, low[i1]); } printf(" "); } return result; } int main(int argc, char const *argv[]) { #ifndef _OJ_ //ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif int i, j, v1, v2, weight, result; Graph g; g = (Graph) malloc (sizeof(Graph1)); scanf("%d %d", &g->nv, &g->ne); for(i = 1;i <= g->nv; i++) { for(j = 1;j <= g->nv; j++) { g->G[i][j] = max; //初始值赋最大 } } for(i = 1;i <= g->ne; i++) { scanf("%d %d %d", &v1, &v2, &weight); g->G[v1][v2] = weight; g->G[v2][v1] = weight;//建立无向图 } for(i = 1;i <= g->nv; i++) visit[i] = 0; //标记初始化为零 result = prim_Graph(g); printf("%d ", result); return 0; }
------------------------------------------------------------------------------------------------------------------------------------------
low2 == 4 low3 == 2 low4 == 3 low5 == 999 low6 == 999
pos == 3 low1 == 0 low2 == 4 low3 == 2 low4 == 1 low5 == 999 low6 == 2
pos == 4 low1 == 0 low2 == 4 low3 == 2 low4 == 1 low5 == 6 low6 == 2
pos == 6 low1 == 0 low2 == 4 low3 == 2 low4 == 1 low5 == 4 low6 == 2
pos == 2 low1 == 0 low2 == 4 low3 == 2 low4 == 1 low5 == 3 low6 == 2
pos == 5 low1 == 0 low2 == 4 low3 == 2 low4 == 1 low5 == 3 low6 == 2
12
-----------------------------------------------------------------------------------------------------------------------------------------------
总而言之每一个low[]数组存入一个最小的权值, 如果遇到更小的便换为更小的;
low[1]---v1
low[2]----v2
------------------
类似于在线处理,, 总保存最小的那一个;;;