普利姆算法:简单地说就是从一个点开始逐步访问所有顶点,每次经过的边是每一次可以走的所有路径中权值最小的那条边,根据这种方法构造最小生成树。
视频示例如下:
//如下代码是完整代码,关于普利姆算法的部分有专门标注!
//本博主所发的所有的文章都有完整代码哦!
//今日,将图学结束
//二维数组存储邻接矩阵
//一维数组存储顶点信息
#include<iostream>
using namespace std;
//-----图的邻接矩阵表示----
#define MaxInt 32767 //表示极大值
#define MVNum 100 //最大顶点数
typedef string VerTexType;//假设顶点的数据类型为字符串型
typedef int ArcType; //假设边的权值类型为字符串型
typedef struct
{
VerTexType vexs[MVNum];//顶点表
ArcType arcs[MVNum][MVNum];//邻接矩阵
int vexnum, arcnum;//图的当前顶点数和边数
}AMGraph;
//采用邻接矩阵表示法创建无向网
/*
1.输入总顶点数和总边数
2.依次输入点的信息并将其存入顶点表中
3.初始化邻接矩阵,使每个权值初始化为极大值
4.构造邻接矩阵,依次输入每条边依附的顶点和其权值,确定两个顶点在图中的位置之后,使相应边赋予相应的权限,
同时使其对称边赋予相同的权值*/
//返回顶点在邻接矩阵中对应的下标
int LocateVex(AMGraph& G, char *v1)
{
for (int i = 0; i<G.vexnum; i++)
{
if (v1 == G.vexs[i])
return i;
}
}
void CreateUDN(AMGraph& G)
{
int i, j, k,w;
string v1,v2;
cin >> G.vexnum >> G.arcnum; //输入总顶点数和总边数
for (i = 0; i < G.vexnum; ++i)
cin >> G.vexs[i]; //依次输入点的信息***顶点数组
for (i = 0; i < G.vexnum; ++i)
for (j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = MaxInt; //初始化邻接矩阵,使每个权值初始化为极大值
for (k = 0; k < G.arcnum; ++k) //构造邻接矩阵
{
cin >> v1 >> v2 >> w; //输入一条边依附的顶点及其权值
i = LocateVex(G, &v1[0]); //确定v1和v2在G中的位置,即顶点数组的下标
j = LocateVex(G, &v2[0]);
G.arcs[i][j] = w; //边<v1,v2>的权值置为w
G.arcs[j][i] = G.arcs[i][j]; //置<v1,v2>的对称边<v2,v1>权值为w
}
}
struct closedge
{
VerTexType adjex;//顶点
ArcType lowcost;//权值
}closedge[MVNum];//该数组用来记录从顶点集U到U-V的权值的最小的边
int Min(struct closedge *p,int G)
{
int min=100,k;
for(int i=0;i<G;i++)
{
if(p[i].lowcost!=0&&p[i].lowcost<min)
{
min=p[i].lowcost;
k=i;
}
}
return k;
}
void show(AMGraph G)
{
for (int i = 0; i < G.vexnum; i++)
{
for (int j = 0; j < G.vexnum; j++)
{
// if (G.arcs[i][j] == MaxInt)
cout << G.arcs[i][j] << "\t";
/// else
// cout << G.arcs[i][j] << "\t";
}
cout << endl<<endl;
}
}
//普利姆算法
void Prim(AMGraph G,char *u)//u为起始顶点
{
int k,j,i;
string u0,v0;
k=LocateVex(G,&u[0]);//k存储u的下标
for(j=0;j<G.vexnum;++j)//对U-V的每一个顶点初始化
if(j!=k)
closedge[j]={u,G.arcs[k][j]};//初始化
closedge[k].lowcost=0;
for(i=1;i<G.vexnum;++i)
{//其余的n-1个顶点生成n-1条边
k=Min(closedge,G.vexnum);//找出边上权最小的边对应的另一个顶点的下标
u0=closedge[k].adjex;//找出最小边在U中的点的下标
v0=G.vexs[k];//找出最小边在U-V中的点的下标
cout<<u0<<"——>"<<v0<<" "<<endl;//输出两点
closedge[k].lowcost=0;//初始化,相当于是标记已访问过了
for(j=0;j<G.vexnum;++j)
if(G.arcs[k][j]<closedge[j].lowcost)//找已经存在U中的最小权
closedge[j]={G.vexs[k],G.arcs[k][j]};
}
}
int main()
{
AMGraph G;
string v;
CreateUDN(G);
show(G);
cin>>v;
Prim(G,&v[0]);
}
输入示例:
6 10
v1 v2 v3 v4 v5 v6
v1 v2 6
v1 v3 1
v1 v4 5
v2 v3 5
v2 v5 3
v3 v5 6
v3 v4 5
v3 v6 4
v4 v6 2
v5 v6 6