Prime算法和kruskal算法是两个利用MST性质构造最小生成树的算法,两个算法都比较简单 代码如下 本文依照如下图所示进行测试
Prime算法
加点法 逐步增加生成树中顶点
#include <iostream>
#include<stdlib.h>
using namespace std;
#define MVNum 100 //最大顶点数
#define MAXInt 10086 //极大值
typedef struct Mgraph
{
char vexs[MVNum]; //顶点表
int arcs[MVNum][MVNum]; //邻接矩阵
int vexnum; //图的当前点数
int arcnum; //图的当前边数
}AMGraph;//Adjacency Matrix Graph
struct edge
{
char adjvex;//最小边在U中的那个顶点
int mincost;//最小边上的权值
}closedge[MVNum];//辅助数组
int LocateVex(AMGraph* G, char v)//找到结点V在图G中的位置 即下标
{
for (int i = 0; i < G->vexnum; i++)
{
if (G->vexs[i] == v)
{
return i;
}
}
cout << "没找到" << endl;
return 0;
}
void CreatAMG(AMGraph* G)//邻接矩阵表示法创建无向网
{
cout << "请输入图的总顶点数与总边数: ";
cin >> G->vexnum >> G->arcnum;//输入总顶点数 总边数
cout << "输入点的信息: ";
for (int i = 0; i < G->vexnum; i++)
{
cin >> G->vexs[i];
}
for (int i = 0; i < G->vexnum; i++)//初始化
{
for (int j = 0; j < G->vexnum; j++)
{
G->arcs[i][j] = MAXInt;
}
}
char v1, v2;//相连结点
int w;//权值
cout << "输入相连结点及边的权值" << endl;
for (int k = 0; k < G->arcnum; k++)//构造邻接矩阵
{
cin >> v1 >> v2 >> w;//表示v1和v2相连接
int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
G->arcs[i][j] = G->arcs[j][i] = w;
}
cout << "邻接矩阵如下" << endl;
for (int i = 0; i < G->vexnum; i++)
{
for (int j = 0; j < G->vexnum; j++)
{
cout << G->arcs[i][j] << " ";
}
cout << "\n";
}
return;
}
int Min(struct edge* closedge, AMGraph* G)
{
int min = MAXInt;
int ret = -1;
for (int i = 0; i < G->vexnum; i++)
{
if (closedge[i].mincost != 0 && min > closedge[i].mincost)
{
min = closedge[i].mincost;
ret = i;
}
}
return ret;
}
void miniSpanTree_Prime(AMGraph* G, char u)
{
/*
* closedge[i].mincost==0 说明i对应的顶点被加入U
*/
int k = LocateVex(G, u);//寻找顶点u在G中的位置(vexs中的下标)
for (int i = 0; i < G->vexnum; i++)
{
if (i != k)
{
closedge[i] = { u,G->arcs[k][i] };
}
}
closedge[k].mincost = 0;//初始化 U={u}
cout << "最小生成树如下" << endl;
for (int i = 1; i < G->vexnum; i++)
{
k = Min(closedge, G);
char u0 = closedge[k].adjvex;
char v0 = G->vexs[k];
cout << u0 << v0;
closedge[k].mincost = 0;
for (int j = 0; j < G->vexnum; j++)//更新closedge数组
{
if (G->arcs[k][j] < closedge[j].mincost)
closedge[j] = { G->vexs[k],G->arcs[k][j] };
}
}
}
int main()
{
AMGraph* G = (AMGraph*)malloc(sizeof(AMGraph));
if (G == NULL)
{
cout << "空间不足 创建失败" << endl;
return 0;
}
CreatAMG(G);
miniSpanTree_Prime(G, 'A');
return 0;
}
测试结果如下
Kruskal算法
归并边 代码如下
#include <iostream>
#include<algorithm>
using namespace std;
#define MVNum 100 //最大顶点数
#define MAXInt 10086 //极大值
typedef struct Mgraph
{
char vexs[MVNum]; //顶点表
int arcs[MVNum][MVNum]; //邻接矩阵
int vexnum; //图的当前点数
int arcnum; //图的当前边数
}AMGraph;//Adjacency Matrix Graph
struct Edge
{
char head;//最小边在U中的那个顶点
char tail;//最小边上的权值
int weight;
}edge[MVNum];//辅助数组
int LocateVex(AMGraph* G, char v)//找到结点V在图G中的位置 即下标
{
for (int i = 0; i < G->vexnum; i++)
{
if (G->vexs[i] == v)
{
return i;
}
}
cout << "没找到" << endl;
return 0;
}
void CreatAMG(AMGraph* G)//邻接矩阵表示法创建无向网
{
cout << "请输入图的总顶点数与总边数: ";
cin >> G->vexnum >> G->arcnum;//输入总顶点数 总边数
cout << "输入点的信息: ";
for (int i = 0; i < G->vexnum; i++)
{
cin >> G->vexs[i];
}
for (int i = 0; i < G->vexnum; i++)//初始化
{
for (int j = 0; j < G->vexnum; j++)
{
G->arcs[i][j] = MAXInt;
}
}
char v1, v2;//相连结点
int w;//权值
cout << "输入相连结点及边的权值" << endl;
for (int k = 0; k < G->arcnum; k++)//构造邻接矩阵
{
cin >> v1 >> v2 >> w;//表示v1和v2相连接
edge[k] = { v1,v2,w };
int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
G->arcs[i][j] = G->arcs[j][i] = w;
}
cout << "邻接矩阵如下" << endl;
for (int i = 0; i < G->vexnum; i++)
{
for (int j = 0; j < G->vexnum; j++)
{
cout << G->arcs[i][j] << " ";
}
cout << "\n";
}
return;
}
bool cmp(struct Edge a, struct Edge b)
{
return a.weight < b.weight;
}
int vexset[MVNum];
void miniSpanTree_Krusal(AMGraph* G, char u)
{
sort(edge, edge + G->arcnum, cmp);
for (int i = 0; i < G->vexnum; i++)
{
vexset[i] = i; //各顶点自成连通分量 vexset中值一样的话 说明同属一个连通分量
}
for (int i = 0; i < G->arcnum; i++)
{
int v1 = LocateVex(G, edge[i].head);
int v2 = LocateVex(G, edge[i].tail);
int vs1 = vexset[v1];//获取边所在的连通分量
int vs2 = vexset[v2];
if (vs1 != vs2)//如果不属于同一连通分量
{
cout << edge[i].head << "--" << edge[i].tail << endl;//输出此边
for (int j = 0; j < G->vexnum; j++)
{
if (vexset[j] == vs2)
{
vexset[j] = vs1;//合并两个连通分量
}
}
}
}
}
int main()
{
AMGraph* G = (AMGraph*)malloc(sizeof(AMGraph));
if (G == NULL)
{
cout << "空间不足 创建失败" << endl;
return 0;
}
CreatAMG(G);
cout << "最小生成树如下" << endl;
miniSpanTree_Krusal(G, 'A');
return 0;
}
测试结果如下
Kruskal算法更适合求稀疏网的最小生成树