Prim算法又叫“加点法”,适用于稠密图。
// Prim(最小生成树).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
#define MAXNUM 255
#define INFINITY 65535
typedef char vexType; //顶点类型
typedef int arcType; //边的权值类型
/// <summary>
/// 无向网G
/// </summary>
typedef struct
{
vexType vexs[MAXNUM];
arcType arcs[MAXNUM][MAXNUM];
int vexsNum, arcsNum;
}AMGraph;
/// <summary>
/// 存储路径信息
/// </summary>
typedef struct
{
vexType head;
vexType tail;
arcType lowcost;
}Edge[MAXNUM];
/// <summary>
/// 找到图中的顶点
/// </summary>
/// <param name="G">无向图G</param>
/// <param name="v">顶点</param>
/// <returns>下标</returns>
int LocateVex(AMGraph G, vexType v)
{
for (int i = 0; i < G.vexsNum; i++)
{
if (v == G.vexs[i])
return i;
}
cout << "没有这个顶点!" << endl;
return 0;
}
/// <summary>
/// 创建无向图的邻接矩阵
/// </summary>
/// <param name="G">无向图G</param>
void createGraph(AMGraph* G)
{
vexType v1, v2;
arcType w;
int cnt = 1;
cout << "请输入城市的规模和路径数目" << endl;
cin >> G->vexsNum >> G->arcsNum;
cout << "请输入城市" << endl;
for (int i = 0; i < G->vexsNum; i++)
{
cin >> G->vexs[i];
}
//初始化邻接矩阵
for (int i = 0; i < G->vexsNum; i++)
{
for (int j = 0; j < G->vexsNum; j++)
G->arcs[i][j] = INFINITY;
}
//初始化完成
cout << "请输入两个城市及路径权值" << endl;
for (int i = 0; i < G->arcsNum; i++)
{
cin >> v1 >> v2 >> w;
int m = LocateVex(*G, v1);
int n = LocateVex(*G, v2);
G->arcs[m][n] = w;
G->arcs[n][m] = G->arcs[m][n];
}
}
/// <summary>
/// 寻找与被标记的顶点有关的最小权值的边
/// </summary>
/// <param name="G">图</param>
/// <param name="visit">判断结点是否被访问的数组</param>
int findMin(AMGraph G,bool *visit,Edge closedge)
{
int i, j, k, cnt = 0;
int min = INFINITY;
for (i = 0; i < G.vexsNum; i++)
{
if (true == visit[i])
{
for (j = 0; j < G.vexsNum; j++)
{
if (false == visit[j] && G.arcs[i][j] < min)
{
min = G.arcs[i][j];
closedge[cnt].head = G.vexs[i];
closedge[cnt].tail = G.vexs[j];
k = j;
}
}
}
}
visit[k] = true;
closedge[cnt++].lowcost = min;
//for (int i = 0; i < G.vexsNum; i++)
// cout << visit[i] << " ";
cout << " 路径:";
cout << closedge[cnt-1].head << "-" << closedge[cnt-1].tail << " $" << closedge[cnt-1].lowcost;
cout << endl;
return min;
}
/// <summary>
/// Prim
/// </summary>
/// <param name="G">图</param>
void MiniSpanTree_prim(AMGraph* G)
{
int price = 0;
Edge closedge;
bool visited[MAXNUM];
memset(visited, false, sizeof(visited));
visited[0] = true;
cout << "<-最低经济代价的通信网->" << endl;
for (int i = 0; i < G->vexsNum - 1;i++)
{
price+=findMin(*G,visited,closedge);
}
cout << "总代价为:" << price;
}
int main(int argc, char* argv[])
{
AMGraph G;
//采用邻接矩阵表示无向网G
createGraph(&G);
//cout << "无向图的邻接矩阵为:" << endl;
//for (int i = 0; i < G.vexsNum; i++)
//{
// for (int j = 0; j < G.vexsNum; j++)
// cout << G.arcs[i][j] << "\t ";
// cout << endl;
//}
//根据邻接矩阵,利用Prim算法得到最小生成树
MiniSpanTree_prim(&G);
return 0;
}
Kruskal 又叫“加边法”,适用于稀疏图。
// Kruskal(最短路径).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
#define MAXNUM 255
#define INFINITY 65535
typedef char vexType; //顶点类型
typedef int arcType; //边的权值类型
typedef struct
{
vexType vexs[MAXNUM];
arcType arcs[MAXNUM][MAXNUM];
int vexsNum, arcsNum;
}AMGraph;
/// <summary>
/// 存储路径信息
/// </summary>
struct Edge
{
vexType head;
vexType tail;
arcType lowcost;
};
/// <summary>
/// 快速排序
/// </summary>
/// <param name="a">第一个参数</param>
/// <param name="b">第二个参数</param>
/// <returns>比较结果</returns>
int cmp(const void* a, const void* b) {
return ((struct Edge*)a)->lowcost - ((struct Edge*)b)->lowcost;
}
/// <summary>
/// 找到图中的顶点
/// </summary>
/// <param name="G">无向图G</param>
/// <param name="v">顶点</param>
/// <returns>下标</returns>
int LocateVex(AMGraph G, vexType v)
{
for (int i = 0; i < G.vexsNum; i++)
{
if (v == G.vexs[i])
return i;
}
cout << "没有这个顶点!" << endl;
return 0;
}
/// <summary>
/// 创建无向图的邻接矩阵
/// </summary>
/// <param name="G">无向图G</param>
void createGraph(AMGraph* G,Edge closedge[])
{
vexType v1, v2;
arcType w;
int cnt = 0;
cout << "输入图的顶点数和边的条数" << endl;
cin >> G->vexsNum >> G->arcsNum;
cout << "输入顶点" << endl;
for (int i = 0; i < G->vexsNum; i++)
{
cin >> G->vexs[i];
}
//初始化邻接矩阵
for (int i = 0; i < G->vexsNum; i++)
{
for (int j = 0; j < G->vexsNum; j++)
G->arcs[i][j] = INFINITY;
}
//初始化完成
cout << "输入边的两个顶点和权值" << endl;
for (int i = 0; i < G->arcsNum; i++)
{
cin >> v1 >> v2 >> w;
int m = LocateVex(*G, v1);
int n = LocateVex(*G, v2);
G->arcs[m][n] = w;
G->arcs[n][m] = G->arcs[m][n];
closedge[i].head = G->vexs[m];
closedge[i].tail = G->vexs[n];
closedge[i].lowcost = w;
}
}
/// <summary>
/// Kruskal
/// </summary>
/// <param name="G">无向图</param>
/// <param name="closedge">路径信息</param>
void MiniSpanTree_kruskal(AMGraph* G,Edge closedge[]) {
int visit[MAXNUM];
int price = 0;
//初始化标记各不相同
for (int i = 0; i < G->vexsNum; i++)
{
visit[i] = i;
}
qsort(closedge, G->arcsNum, sizeof(closedge[0]), cmp);
cout << "<-最低经济代价的通信网->" << endl;
for (int i = 0; i < G->arcsNum; i++)
{
int head = LocateVex(*G,closedge[i].head);
int tail = LocateVex(*G, closedge[i].tail);
if (visit[head] != visit[tail])
{
cout << closedge[i].head << "-" << closedge[i].tail<<" $"<<closedge[i].lowcost;
price += closedge[i].lowcost;
cout << endl;
int temp = visit[head];
for (int j = 0; j < G->vexsNum; j++)
{
if (visit[j] == temp)
{
visit[j] = visit[tail];
}
}
}
}
cout << "总代价为:" << price;
}
int main(int argc, char* argv[])
{
Edge closedge[MAXNUM];
AMGraph G;
createGraph(&G,closedge);
MiniSpanTree_kruskal(&G, closedge);
return 0;
}