四、最小生成树——普里姆(Prim)算法

        一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边,那么我们把构造连通图网的最小代价生成树称为最小生成树(就是n个顶点,用n-1条边全部连接起来,并且使得权值的和最小)。

现在有如下一个图,以及它的邻接矩阵:

我们用下面的算法来寻找最小生成树

#include<iostream>
#include<vector>
#include<queue>
using namespace std;

#define MAXVEX 100//最大顶点数
typedef char VertexType;//顶点类型
typedef int EdgeType;//边上的权值类型
typedef struct
{
	VertexType vexs[MAXVEX];//顶点表
	EdgeType arc[MAXVEX][MAXVEX];//邻接矩阵
	int numVertexte;//当前顶点数
	int numEdges;//当前边数
}MGraph;

void MiniSpanTree_Prim(MGraph G)
{
	vector<int> lowcost(MAXVEX);/*保存相关顶点间边的权值,具体的lowcost[i]代表的是:在最小生成树中 从v0到顶点i的最短距离(最小权值)*/
	vector<int> adjvex(MAXVEX);/*保存相关顶点下标,具体的adjvex[i]代表的是:在最小生成树中 顶点i的上一个顶点为adjvex[i]*/

	lowcost[0] = 0;/*表示V0已经被纳入到最小生成树中,之后凡是lowcost数组中的值被设置为0就是表示此下标的顶点被纳入最小生成树。*/
	adjvex[0] = 0;/*意思就是我们现在从顶点v0开始(事实上,最小生成树从哪个顶点开始计算都无所谓,我们假定从v0开始)*/

	for (int i = 1; i < G.numVertexte; ++i)
	{
		lowcost[i] = G.arc[0][i];//即lowcost存放的是顶点v0~顶点i的权值
		adjvex[i] = 0;/*初始化顶点i的上一个节点都为v0*/
	}

	for (int i = 1; i < G.numVertexte; ++i)
	{
		int min = INT_MAX;//保存当前的最小权值
		int k = 0;//保存最小权值所在的下标
		for (int j = 1; j < G.numVertexte; ++j)
		{
			if (lowcost[j] != 0 && lowcost[j] < min)//如果顶点j还没有被纳入最小生成树且顶点v0到顶点j的权小于之前的最小权,则更新min和k
			{
				min = lowcost[j];
				k = j;
			}
		}
		cout << adjvex[k] << " " << k;//分别输出顶点k的上一个顶点和顶点k
		lowcost[k] = 0;//将顶点k加入最小生成树
		for (int j = 1; j < G.numVertexte; ++j)
		{
			if (lowcost[j] != 0 && G.arc[k][j] < lowcost[j])//如果顶点j还没被纳入最小生成树,并且从顶点k到顶点j的权值 小于 从顶点v0到顶点j的权值
			{
				lowcost[j] = G.arc[k][j];//那么从v0->j 就可以变为 v0->k->j
				adjvex[j] = k;//此时顶点j的上一个顶点为k
			}
		}
	}
}

该算法的时间复杂度为:O(n^{2})

猜你喜欢

转载自blog.csdn.net/ThinPikachu/article/details/123624325