最小生成树的普利姆prim算法代码实现

算法的原理很简单,即用贪心的思想选出据已选顶点最近顶点添加到顶点集中,本文不过多赘述,本文内容主要为该算法的C++代码实现,另外图的存储结构使用邻接矩阵。

直接上代码:

#include<iostream>
using namespace std;
#define INF 9999//假定图中所有点之间的距离都不超过这个数字
struct Arc {
	int V1;
	int V2;
	int weight;//权重
};
class map {
	int** matrix;
	string* ch;//顶点对应的字符
	int n;//顶点数
	Arc* arc;//边
	int arcnum;//边数
	bool* visited;//标记顶点是否已经被访问过
	int* dis;//各顶点据已访问顶点集的距离,每次顶点集有新的顶点加入,dis数组都要更新一次
	int res;//最小生成树的权值
	string Vmin;//这个变量为“最小顶点”,记录新加入的顶点是从哪个顶点过去的,是为了让树的生长过程更显而易见
public:
	int LocateVex(string u) {
		for (int i = 0; i < n; i++) {
			if (u == ch[i]) {
				return i;
			}
		}
		cout << "不存在该顶点,程序运行失败";
		return -1;
	}
	map(int n) {
		this->n = n;
		res = 0;
		dis = new int[n];
		//邻接矩阵,设置其初始值为最大值
		for (int i = 0; i < n; i++)dis[i] = INF;
		matrix = new int* [n];
		for (int i = 0; i < n; i++) {
			*(matrix + i) = new int[n];
			for (int j = 0; j < n; j++)matrix[i][j] = INF;
		}
		//初始化visited数组,一开始全为未访问顶点
		visited = new bool[n];
		for (int i = 0; i < n; i++) {
			visited[i] = false;
		}
		//输入n个顶点
		ch = new string[n];
		for (int i = 0; i < n; i++) {
			cin >> ch[i];
		}
		//先输入边数
		cin >> arcnum;
		arc = new Arc[arcnum];
		//然后按v1,v2,weight的格式输入arcnum条边及其权值
		for (int i = 0; i < arcnum; i++) {
			string v1, v2;
			cin >> v1 >> v2;
			int x = search_V(v1);
			int y = search_V(v2);
			//记录边两头的顶点
			arc[i].V1 = x;
			arc[i].V2 = y;
			cin >> arc[i].weight;
			//无向图
			matrix[LocateVex(v1)][LocateVex(v2)] = arc[i].weight;
			matrix[LocateVex(v2)][LocateVex(v1)] = arc[i].weight;
		}
	}
	//最小生成树的生长过程中,树每一次开始生长的顶点必然是距未访问顶点集最小的顶点
	//比较 新加入的顶点与未访问顶点集的距离 和 上一次距未访问顶点集距离最小的顶点距未访问顶点集的距离 哪个比较小
	//若新加入的小,则更新最小顶点
	void check(int t) {
		int temp = INF; int t1 = 0;
		for (int i = 0; i < n; i++) {
			if (visited[i] && matrix[t][i] < temp) {
				temp = matrix[t][i];
				t1 = i;
			}
		}
		Vmin = ch[t1];
	}
	void update_dis(int t) {//将t结点加入后,用t结点为准更新dis数组
		for (int i = 0; i < n; i++) {
			if (!visited[i] && dis[i] > matrix[t][i]) {
				dis[i] = matrix[t][i];
			}
		}
	}
	//prim算法
	void prim(string v) {//参数是开始建树的顶点
		cout << "prim:" << endl;
		//设置最小顶点为当前顶点
		Vmin = v;
		int i = LocateVex(v);
		//标记第一个顶点已访问
		visited[i] = true;
		dis[i] = 0;
		for (int j = 0; j < n; j++) {
			if (j == i)continue;
			dis[j] = min(matrix[i][j], dis[j]);
		}
		for (int m = 0; m < n - 1; m++) {//一共有n个结点,要把所有结点加入到生成树,所以添加n-1次
			int temp = INF;
			int t = 0;
			for (int k = 0; k < n; k++) {//检索结点,如果未添加到树中且与树集合有连接边且新的边权重小于之前边
				if (!visited[k] && dis[k] < temp) {
					temp = dis[k];//则记录当前距树集合最短边权重
					t = k;//记录这条边的下标
				}
			}
			check(t);
			cout << Vmin << " ";
			cout << ch[t] << " ";
			visited[t] = true;
			res += dis[t];
			cout << dis[t] << endl;
			update_dis(t);//更新dis	
		}
      //cout<<"res="<<res<<endl;//最小生成树权值
	}
	int search_V(string u) {
		for (int i = 0; i < n; i++) {
			if (u == ch[i])return i;
		}
		return -1;
	}

	~map() {
		for (int i = 0; i < n; i++) {
			delete[]matrix[i];
		}
		delete[]matrix;
		delete[]arc;
		delete[]dis;
		delete visited;
	}
};
int main() {

	int n;//顶点数
	cin >> n;
	map a(n);
	string v;
	cin >> v;
	//v:普利姆算法开始的顶点
	a.prim(v);
}

输入样例:

6
v1 v2 v3 v4 v5 v6 
10
v1 v2 6
v1 v3 1
v1 v4 5
v2 v3 5
v2 v5 3
v3 v4 5
v3 v5 6
v3 v6 4
v4 v6 2
v5 v6 6
v1

输出结果:

prim:
v1 v3 1
v3 v6 4
v6 v4 2
v3 v2 5
v2 v5 3
对算法或者代码有疑问的可以评论或私信,看到了都会回

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值