目录
Prim算法是一种用于解决图的最小生成树问题的贪心算法。最小生成树是一个连通图的子图,它包含图中所有的顶点,但是只有足够的边使得这个子图成为一个树,且边的权重之和最小。Prim算法能够帮助我们找到连接所有顶点的最小权重的边,构建最小生成树。
1. 基本思想
Prim算法从一个起始顶点开始(任意一个顶点),逐步扩展最小生成树,直到覆盖所有顶点。它在每一步选择当前已经在最小生成树中的顶点和不在最小生成树中的顶点之间的最小权重的边,将该边的另一端顶点加入最小生成树,同时将该边添加到最小生成树的边集合中。
2. 算法步骤
- 初始化:选择一个起始顶点,将其加入最小生成树中,初始化最小生成树的边集合为空。
- 选择边:在不在最小生成树中的顶点中,选择与最小生成树中的顶点连接且权重最小的边。
- 更新最小生成树:将选择的边的另一端顶点加入最小生成树,将该边添加到最小生成树的边集合中。
- 重复步骤2和3,直到最小生成树覆盖所有顶点。
3. Prim算法的实现
使用下面的图来实现Prim算法,下面右图是左图所生成的最小生成树
以下是我们将上面的例图执行Prim算法的完整代码
#include<iostream>
#include<vector>
using namespace std;
#define V 6 //顶点个数
int graph[V][V] = { //图的邻接矩阵表示
{0,6,0,0,5,1},
{6,0,3,0,0,5},
{0,3,0,6,0,6},
{0,0,6,0,2,4},
{5,0,0,2,0,4},
{1,5,6,4,4,0}
};
vector<int> order; //加入最小生成树的顺序
int min_weight[V]; //某个顶点目前到生成树的最小边权
bool isJoin[V]; //记录顶点是否已经加入最小生成树
int weightSum = 0; //最小生成树的权值和
//返回min_weight中 不在生成树中的顶点 到生成树的最小权值
int minWeight(int &min_index) { //min_index带回最小值下标
int min = INT_MAX;
for (int j = 0; j < V; j++) {
if (!isJoin[j] && min_weight[j] < min) {
min = min_weight[j];
min_index =j;
}
}
return min;
}
void printMST() {
cout << "Prim算法生成的最小生成树的权值和为:" << weightSum << endl;
for (int i = 0; i < V; i++) {
cout << "第" << i + 1 << "个加入最小生成树的顶点下标是" << order[i]
<<"\t其对应的权值是"<<min_weight[order[i]] << endl;
}
cout << endl;
}
void primMST(int begin) { //begin是挑选从哪个顶点开始执行算法
for (int i = 0; i < V; i++) {
//初始化min_weight数组都是无穷大,后面会更新
min_weight[i] = INT_MAX;
//与begin相关联的边的权值对应更新到min_weight数组
if (graph[begin][i]) {
min_weight[i] = graph[begin][i];
}
}
min_weight[begin] = 0; //第一个顶点到自己的权值为0
order.push_back(begin); //第一个加入最小生成树的是begin
isJoin[begin] = true; //加入最小生成树
for (int i = 0; i < V-1;i++) { //每次循环都选择一个顶点加入生成树一共V-1个
int newTNode = -1; //要加入的顶点的下标
int getMin = minWeight(newTNode); //newTNode被更新 getMin为能连到当前的生成树的最小边权值
weightSum += getMin; //每次的getMin加起来
order.push_back(newTNode); //记录加入最小生成树的顺序
isJoin[newTNode] = true; //加入最小生成树
//每加入一个顶点到最小生成树中,由于加入了一个新顶点,导致最优选择可能会改变
//所以我们要再扫一遍min_weight数组,更新它
for (int j = 0; j < V; j++) {
//每次都只需要讨论新加入的顶点newTNode,基于贪心策略,每次都是当前最优
//不在生成树中的顶点 且 跟新加入的顶点newTNode有关联 且 这条边的边权比原来的小
if(!isJoin[j]&&graph[j][newTNode] && graph[j][newTNode]<min_weight[j]) {
min_weight[j] = graph[j][newTNode];
}
}
}
printMST();
}
int main() {
primMST(5);
return 0;
}
4. 测试结果
完全正确!!!
点个关注吧~~~~~~~