Prim最小生成树算法实现思路
思路
- 从某一个顶点开始创建树
- 从生成树与未加入生成树的顶点相连的边中选取最小开销的边加入生成树
- 更新生成树到未加入生成树的顶点的开销
- 反复2,3步骤
逻辑存储结构
typedef struct Adjacenc_Matrix
{
int vex[MaxSize];
int T[MaxSize][MaxSize];
} Adjacenc_Matrix;
typedef struct Prim
{
bool isjoin[MaxSize];//标记顶点是否加入生成树
int lowCost[MaxSize];//记录顶点到生产树的最小开销
Adjacenc_Matrix Adj;
} Prim;
例如从v0开始创建最小生成树
-
首先初始化,存入生成树{v0}到未加入生成树的顶点{v1,v2,v3,v4,v5}的距离
顶点下标 0 1 2 3 4 5 isjoin 1 0 0 0 0 0 lowCost 0 6 5 1 无穷 无穷 -
从生成树{v0}与未加入生成树的顶点{v1,v2,v3,v4,v5}的边中选取最小开销的边加入生成树,即(v0,v3)
-
如果生成树{v0,v3}与未加入生成树的顶点{v1,v2,v4,v5}的距离小于原来的距离,则更新
-
新加入生成树的v3到v1的开销为:5<6,更新
-
新加入生成树的v3到v2的开销为:4<5,更新
-
新加入生成树的v3到v4的开销为:6<65535,更新
-
新加入生成树的v3到v5的开销为:4<65535,更新
顶点下标 0 1 2 3 4 5 isjoin 1 0 0 0 0 0 lowCost 0 6->5 5->4 1 无穷->6 无穷->4
-
-
重复步骤2,3,则可生成最小生成树
全部代码
#include <iostream>
#include <string>
using namespace std;
#define MaxSize 6
#define InitWeight 65535
typedef struct Adjacenc_Matrix
{
int vex[MaxSize];
int T[MaxSize][MaxSize];
} Adjacenc_Matrix;
typedef struct Prim
{
bool isjoin[MaxSize];
int lowCost[MaxSize];
Adjacenc_Matrix Adj;
} Prim;
bool Init(Prim &p)
{
for (int i = 0; i < MaxSize; i++)
{
cin >> p.Adj.vex[i];
p.isjoin[i] = false;
for (int j = 0; j < MaxSize; j++)
{
if (i == j)
{
p.Adj.T[i][j] = 0;
continue;
}
p.Adj.T[i][j] = InitWeight;
}
}
return true;
}
bool CreateTable(Prim &p)
{
for (int i = 0; i < MaxSize; i++)
{
int j, weight;
cin >> p.Adj.vex[i];
while (true)
{
if (cin.get() == '\n')
{
break;
}
cin >> j >> weight;
p.Adj.T[i][j] = weight;
}
}
return true;
}
//遍历邻接矩阵
void VisitAdj(Prim p)
{
printf("------------------邻接矩阵------------------\n");
for (int i = 0; i < MaxSize; i++)
{
for (int j = 0; j < MaxSize; j++)
{
printf("%d\t", p.Adj.T[i][j]);
}
printf("\n");
}
printf("------------------------------------------\n");
}
void VisitIsjoinLowCost(Prim p)
{
printf("------------------------------------------\n");
for (int i = 0; i < MaxSize; i++)
{
printf("%d\t", p.isjoin[i]);
}
printf("\n");
for (int i = 0; i < MaxSize; i++)
{
printf("%d\t", p.lowCost[i]);
}
printf("\n");
printf("------------------------------------------\n");
}
void GetMinWeight(Prim p)
{
int sum = 0;
for (int i = 0; i < MaxSize; i++)
{
sum += p.lowCost[i];
}
printf("最小生成树权值之和:%d\n", sum);
}
bool MinSpanTree(Prim &p, int start)
{
//初始化
p.isjoin[start] = true;
for (int i = 0; i < MaxSize; i++)
{
p.lowCost[i] = p.Adj.T[start][i];
}
//构建最小生成树
VisitIsjoinLowCost(p);
for (int k = 1; k < MaxSize; k++)
{
//找出与生成树相连并且最小开销的路径,并加入生成树
int min = InitWeight;
int index;
for (int i = 0; i < MaxSize; i++)
{
if (p.lowCost[i] < min && !p.isjoin[i])
{
min = p.lowCost[i];
index = i;
}
}
printf("min:%d index:%d\n", min, index);
p.isjoin[index] = true;
for (int i = 0; i < MaxSize; i++)
{
//如果新加入生成树的顶点到未加入生成树的顶点开销<原来的开销,则更新生成树到未加入生成树的顶点开销
if (!p.isjoin[i] && p.Adj.T[i][index] < p.lowCost[i])
{
p.lowCost[i] = p.Adj.T[i][index];
}
}
VisitIsjoinLowCost(p);
}
return true;
}
int main()
{
/*
0 1 2 3 4 5
0 1 6 2 5 3 1
1 0 6 3 5 4 3
2 0 5 3 4 2 5
3 0 1 1 5 4 6 5 4 2 4
4 1 3 3 6 5 6
5 4 6 3 4 2 2
*/
Prim p;
Init(p);
CreateTable(p);
VisitAdj(p);
MinSpanTree(p, 0);
GetMinWeight(p);
}