普里姆算法(prim)
(图来源于百度百科:prim)
时间复杂度为:O(n^2),与网中的边数无关,因此适合于求稠密网的最小生成树。
prim的代码:
void prim(AMGraph G, int u)
{
int k;
for(int i=0; i<G.vex; ++i) //查找u在顶点集的位置
if(G.vs[i] == u)
{
k = i;
break;
}
for(int j=0; j<G.vex; ++j) //对V-U的每一个顶点Vj,初始化edge
{
//初始化,U = {u}
if(j!=k)
{
edge[j].adjvex = u;
edge[j].lowcost = G.a[k][j];
}
}
// edge[k].adjvex = u;
edge[k].lowcost = 0; //自己到自己。。。。
for(int i=1; i<G.vex; ++i) //选择其余n-1个顶点,生成n-1条边
{
int minn = INF+1, x;
for(int j=0; j<G.vex; ++j) //在V-U中找到和U中相连的最小权值点。
{
if(edge[j].lowcost < minn && edge[j].lowcost!=0)
{
minn = edge[j].lowcost;
x = j;
}
}
k = x;
int u0 = edge[k].adjvex;
int v0 = G.vs[k]; //输出一下
cout << u0 << "--->" << v0 << '\n';
edge[k].lowcost = 0; //第k个点并入U集
for(int j=0; j<G.vex; ++j) //新顶点并入U后重新选择最小边
if(G.a[k][j] < edge[j].lowcost)
{
edge[j].adjvex = G.vs[k];
edge[j].lowcost = G.a[k][j];
}
}
}
放个栗子,好吧,其实这是我们的数据结构实验。。。
//#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<math.h>
using namespace std ;
typedef long long ll;
#define MAXN 105
#define INF 0x3f3f3f3f
#define MALL (Bithrnode *)malloc(sizeof(Bithrnode));
typedef struct
{
int vs[MAXN]; //顶点表
int a[MAXN][MAXN]; //邻接矩阵
int vex, arc; //图的当前点数和边数
} AMGraph;
struct
{
int adjvex; //最小边在U中的那个顶点
int lowcost; //最小边上的权
} edge[MAXN];
void init(AMGraph &G) //创建邻接矩阵
{
cout << "请输入顶点数vex和边数arc:" << '\n';
cin >> G.vex >> G.arc; //输入点数和边数
cout << "请依次输入各个顶点的代号(可以用int, char和string)" << '\n';
for(int i=0; i<G.vex; ++i)
cin >> G.vs[i];
for(int i=0; i<G.vex; ++i) //初始化矩阵,边的权值为无穷大INF
for(int j=0; j<G.vex; ++j)
G.a[i][j] = INF;
cout << "请输入arc条边与边的关系" << '\n';
for(int k=0; k<G.arc; ++k)
{
int u, v, len, i, j;
cin >> u >> v >> len;
for(int c=0; c<G.vex; ++c) //查找u、v在顶点集中的位置
{
if(G.vs[c] == u)
i = c;
if(G.vs[c] == v)
j = c;
}
G.a[i][j] = len;
G.a[j][i] = len;
}
}
void prim(AMGraph G, int u)
{
int k;
for(int i=0; i<G.vex; ++i) //查找u在顶点集的位置
if(G.vs[i] == u)
{
k = i;
break;
}
for(int j=0; j<G.vex; ++j) //对V-U的每一个顶点Vj,初始化edge
{
//初始化,U = {u}
if(j!=k)
{
edge[j].adjvex = u;
edge[j].lowcost = G.a[k][j];
}
}
// edge[k].adjvex = u;
edge[k].lowcost = 0; //自己到自己。。。。
for(int i=1; i<G.vex; ++i) //选择其余n-1个顶点,生成n-1条边
{
int minn = INF+1, x;
for(int j=0; j<G.vex; ++j) //在V-U中找到和U中相连的最小权值点。
{
if(edge[j].lowcost < minn && edge[j].lowcost!=0) //避免找到自己了。。
{
minn = edge[j].lowcost;
x = j;
}
}
k = x;
int u0 = edge[k].adjvex;
int v0 = G.vs[k];
cout << u0 << "--->" << v0 << '\n';
edge[k].lowcost = 0; //第k个点并入U集
for(int j=0; j<G.vex; ++j)
if(G.a[k][j] < edge[j].lowcost) //新顶点并入U后重新选择最小边
{
edge[j].adjvex = G.vs[k];
edge[j].lowcost = G.a[k][j];
}
}
}
int main()
{
AMGraph G;
init(G);
cout << " 正在使用prim算法进行最小生成树,请稍等...... " << '\n';
prim(G, 0);
}
样例测试:
6 10
0 1 2 3 4 5
0 1 6
0 3 5
0 2 1
1 2 5
2 3 5
1 4 3
2 4 6
2 5 4
3 5 2
4 5 6
输出结果: