最小生成树prim算法实现
今天从志权师兄那里学会了最小生成树。所谓生成树,就是n个点之间连成n-1条边的图形。而最小生成树,就是权值(两点间直线的值)之和的最小值。
首先,要用二维数组记录点和权值。如上图所示无向图:
int map[7][7];
map[1][2]=map[2][1]=4;
map[1][3]=map[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;
3.如此类推...
![](https://i-blog.csdnimg.cn/blog_migrate/faef43dd22af0186e8016d6cfef809be.jpeg)
所有权值相加就是最小生成树,其值为2+1+2+4+3=12。
#include <iostream>
#include <stdio.h>
using namespace std;
const int MAXNUM = 10;
void prim(int graph[MAXNUM][MAXNUM], int n)
{
int v[MAXNUM] = {0};
int closest[MAXNUM] = {0xffff};
int result[MAXNUM] = {0};
int i, pos, j, min;
int sum = 0;
if (n <= 0)
return;
for (i = 0; i <= n; i++)
closest[i] = 0xffff;
pos = 0;
v[0] = 1;
result[0] = pos;
closest[0] = graph[pos][0];
for (i = 1; i < n; i++)
{
min = n;
//update the closest[] according to the pos.
for (j = 0; j < n; j++)
{
if (v[j] != 1)
{
if (graph[pos][j] < closest[j])
closest[j] = graph[pos][j];
if (closest[min] > closest[j])
min = j;
}
}
if (min != n)
{
sum += closest[min];
pos = min;
v[pos] = 1;
result[i] = pos;
}
}
//output the result
cout<<"from v["<<result[0]<<"]";
for (j = 1; j < n; j++)
{
cout<<"---- "<<"v["<<result[j]<<"]: ";
}
cout<< "shortest distance: "<< sum<<endl;
}
int main (void)
{
const int len = 6;
int graph[MAXNUM][MAXNUM] = {{0, 4, 2, 3, 0xffff, 0xffff},
{4, 0, 5, 4, 3, 0xffff},
{2, 5, 0, 1, 0xffff, 2},
{3, 4, 1, 0, 6, 2},
{0xffff, 3, 0xffff, 6, 0, 4},
{0xffff, 0xffff, 2, 2, 4, 0}
};
prim(graph, len);
}