<C/C++图>最小生成树:Prim算法

一,最小生成树算法基本概念

最小生成树是数据结构中图的一种重要应用,它的要求是从一个有n个节点的带权完全图中选择n-1条边并使这个图仍然连通(也即得到了一棵生成树),同时还要考虑使树的权之和最小。最小生成树可以用,Kruskal(克鲁斯卡尔)算法或Prim(普里姆)算法求出。


1,Prim算法

1),算法简单描述:

1).输入:一个加权连通图,其中顶点集合为V,边集合为E;

2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;

3).重复下列操作,直到Vnew = V:

a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);

b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;

4).输出:使用集合Vnew和Enew来描述所得到的最小生成树

2),下面对算法的图例描述:

绿色顶点及边表示:已经被选中为最小生成树中的顶点

淡蓝色顶点及边表示:当前距离已选中的顶点中的最小权值边及其相连的顶点

蓝色表示顶点及边表示:当前已经选中顶点可达的顶点或者边

图例说明不可选可选已选(Vnew
 

此为原始的加权连通图。每条边一侧的数字代表其权值。---

1,选取任意顶点为起始点,比如D。,
2,顶点ABEF通过单条边与D相连。A是距离D最近的顶点,因此将A及对应边AD以高亮表示。
C, GA, B, E, FD
 

1,下一个顶点为距离DA最近的顶点。BD为9,距A为7,E为15,F为6。因此,FDA最近,因此将顶点F与相应边DF以高亮表示。C, GB, E, FA, D
算法继续重复上面的步骤。距离A为7的顶点B被高亮表示。CB, E, GA, D, F
 

在当前情况下,可以在CEG间进行选择。CB为8,EB为7,GF为11。E最近,因此将顶点E与相应边BE高亮表示。C, E, GA, D, F, B
 

这里,可供选择的顶点只有CGCE为5,GE为9,故选取C,并与边EC一同高亮表示。C, GA, D, F, B, E

顶点G是唯一剩下的顶点,它距F为11,距E为9,E最近,故高亮表示G及相应边EGGA, D, F, B, E, C

现在,所有顶点均已被选取,图中绿色部分即为连通图的最小生成树。在此例中,最小生成树的权值之和为39。A, D, F, B, E, C, G


2,Kruskal算法

Kruskal算法与Prim算法的不同之处在于,Kruskal在找最小生成树结点之前,需要对所有权重边做从小到大排序。将排序好的权重边依次加入到最小生成树中,如果加入时产生回路就跳过这条边,加入下一条边。当所有结点都加入到最小生成树中之后,就找出了最小生成树。


1).算法简单描述

1).记Graph中有v个顶点,e个边

2).新建图Graphnew,Graphnew中拥有原图中相同的e个顶点,但没有边

3).将原图Graph中所有e个边按权值从小到大排序

4).循环:从权值最小的边开始遍历每条边 直至图Graph中所有的节点都在同一个连通分量中

                if 这条边连接的两个节点于图Graphnew中不在同一个连通分量中

                                         添加这条边到图Graphnew

2),下面对算法的图例描述:

(每次所选的边都要与原所选边进行是否为圈的判断)

首先第一步,我们有一张图Graph,有若干点和边 

 

将所有的边的长度排序,用排序的结果作为我们选择边的依据。这里再次体现了贪心算法的思想。资源排序,对局部最优的资源进行选择,排序完成后,我们率先选择了边AD。这样我们的图就变成了右图

 

 

 

在剩下的变中寻找。我们找到了CE。这里边的权重也是5

依次类推我们找到了6,7,7,即DF,AB,BE。

下面继续选择, BC或者EF尽管现在长度为8的边是最小的未选择的边。但是现在他们已经连通了(对于BC可以通过CE,EB来连接,类似的EF可以通过EB,BA,AD,DF来接连)。所以不需要选择他们。类似的BD也已经连通了(这里上图的连通线用红色表示了)。

最后就剩下EG和FG了。当然我们选择了EG。最后成功的图就是右:

 



二,C++模板实现

1,Graph.h代码实现如下:

#include "stdafx.h"
#include "iostream"
#include "queue"
using namespace std;

template<class DistType/*边的权值的类型*/> 
class Edge//边的定义
{
public:
	Edge(int dest, DistType weight)
	{
		m_nposTable=dest;
		m_distWeight=weight; 
		m_pnext=NULL;
	}
	~Edge()
	{

	}
public:
	int m_nposTable;//该边的目的顶点在顶点集中的位置
	DistType m_distWeight;//边的权重值
	Edge<DistType> *m_pnext;//下一条边(注意不是下一个顶点,因为m_nposTable已经知道了这个顶点的位置)
};
//声明
template<class NameType/*顶点集名字类型*/, class DistType/*距离的数据类型*/> class Graph;

template<class NameType/*顶点集名字类型*/, class DistType/*距离的数据类型*/> 
class Vertex//顶点的定义
{
public:
	Vertex()
	{
		padjEdge=NULL;
		m_vertexName=0;
	}
	~Vertex()
	{
		Edge<DistType> *pmove = padjEdge;
		while (pmove)
		{
			padjEdge = pmove->m_pnext;
			delete pmove;
			pmove = padjEdge;
		}
	}

private:
	friend class Graph<NameType,DistType>;//允许Graph类任意访问
	NameType m_vertexName;//顶点中的数据内容
	Edge<DistType> *padjEdge;//顶点的邻边

};


template<class NameType/*顶点集名字类型*/, class DistType/*距离的数据类型*/> 
class Graph
{
public:
	Graph(int size = m_nDefaultSize/*图顶点集的规模*/)
	{
		m_pVertexTable = new Vertex<NameType, DistType>[size];  //为顶点集分配内存
		if (m_pVertexTable == NULL)
		{
			exit(1);
		}
		m_numVertexs=0;
		m_nmaxSize=size;
		m_nnumEdges=0;
	}

	~Graph()
	{
		Edge<DistType> *pmove;
		for (int i=0; i < this->m_numVertexs; i++)
		{
			pmove = this->m_pVertexTable[i].padjEdge;
			if (pmove){
				this->m_pVertexTable[i].padjEdge = pmove->m_pnext;
				delete pmove;
				pmove = this->m_pVertexTable[i].padjEdge;
			}
		}
		delete[] m_pVertexTable;
	}
	int GetNumEdges()
	{//获得边的数目
		return m_nnumEdges/2;
	}
	int GetNumVertexs()
	{//获得顶点数目
		return m_numVertexs;
	}

	bool IsGraphFull() const
	{     //图满的?
		return m_nmaxSize == m_numVertexs;
	}
	//在顶点集中位置为v1和v2的顶点之间插入边
	bool InsertEdge(int v1, int v2, DistType weight=m_Infinity); 
	//插入顶点名字为vertex的顶点
	bool InsertVertex(const NameType vertex);  
	//打印图
	void PrintGraph();   
	//顶点v到其他各个顶点的最短路径(包括自身)
	void Dijkstra(int v, DistType *shotestpath);
	//获取顶点集中位置为v1和v2的顶点之间边的权重值
	DistType GetWeight(int v1, int v2); 
	//获得在顶点集中的位置为v的顶点的名字
	NameType GetVertexValue(int v);
	//用该顶点的名字来寻找其在顶点集中的位置
	int GetVertexPosTable(const NameType vertex);  


	//得到顶点v的邻点中权值最小的那条边
	Edge<DistType> *GetMin(int v, int *visited);   
	//最小生成树
	void Prim(Graph<NameType, DistType> &graph);  

	//深度搜索优先
	void DFS(int v, int *visited);      
	void DFS();
	//广度优先搜索
	void BFS(int v, int *visited);
	void BFS();
	//获取第v个顶点的名字(或者说内容)
	NameType GetVertexName(int v);   
	//获得顶点v的第一个相邻顶点,如果没有就返回-1
	int GetFirst(int v);       
	//获得顶点v1的邻点v2后的邻点
	int GetNext(int v1, int v2);

private:
	Vertex<NameType, DistType> *m_pVertexTable;   //顶点集
	int m_numVertexs;//图中当前的顶点数量
	int m_nmaxSize;//图允许的最大顶点数
	static const int m_nDefaultSize = 10;       //默认的最大顶点集数目
	static const DistType m_Infinity = 65536;  //边的默认权值(可以看成是无穷大)
	int m_nnumEdges;//图中边的数目
	
};


//返回顶点vertexname在m_pVertexTable(顶点集)中的位置
//如果不在顶点集中就返回-1
template<class NameType, class DistType> 
int Graph<NameType, DistType>::GetVertexPosTable(const NameType vertexname)
{
	for (int i=0; i < this->m_numVertexs; i++)
	{
		if (vertexname == m_pVertexTable[i].m_vertexName)
		{
			return i;
		}
	}
	return -1;
}

//打印图中的各个顶点及其链接的边的权重
template<class NameType, class DistType> 
void Graph<NameType, DistType>::PrintGraph()
{
	Edge<DistType> *pmove;
	for (int i=0; i<this->m_numVertexs; i++)
	{
		cout << this->m_pVertexTable[i].m_vertexName << "->";
		pmove = this->m_pVertexTable[i].padjEdge;
		while (pmove)
		{
			cout << pmove->m_distWeight << "->" << this->m_pVertexTable[pmove->m_nposTable].m_vertexName << "->";
			pmove = pmove->m_pnext;
		}
		cout << "NULL" << endl;
	}
}
//获得在顶点集中的位置为v的顶点的名字
template<class NameType, class DistType> 
NameType Graph<NameType, DistType>::GetVertexValue(int v)
{
	if (v<0 || v>=this->m_numVertexs)
	{
		cerr << "查找的顶点位置参数有误,请检查!" <<endl;
		exit(1);
	}
	return m_pVertexTable[v].m_vertexName;

}
//返回顶点v1和v2之间的边权值,
//如果没有直接相连(即不是一条边直接相连)则返回无穷大
template<class NameType, class DistType> 
DistType Graph<NameType, DistType>::GetWeight(int v1, int v2)
{
	if (v1>=0 && v1<this->m_numVertexs && v2>=0 && v2<this->m_numVertexs)
	{
		if (v1 == v2)
		{
			return 0;
		}
		Edge<DistType> *pmove = m_pVertexTable[v1].padjEdge;
		while (pmove)
		{
			if (pmove->m_nposTable == v2)
			{
				return pmove->m_distWeight;
			}
			pmove = pmove->m_pnext;
		}
	}
	
	return m_Infinity;	
}

//顶点依次插入到分配好的顶点集中
template<class NameType, class DistType> 
bool Graph<NameType, DistType>::InsertVertex(const NameType vertexname)
{
	if (IsGraphFull())
	{
		cerr<<"图已经满,请勿再插入顶点!"<<endl;
		return false;
	}else
	{
		this->m_pVertexTable[this->m_numVertexs].m_vertexName = vertexname;
		this->m_numVertexs++;
	}
	
	return true;
}

//在顶点集位置为v1和v2的顶点之间插入权值为weght的边(务必保持输入的准确性,否则.....)
template<class NameType, class DistType> 
bool Graph<NameType, DistType>::InsertEdge(int v1, int v2, DistType weight)
{
	if (v1 < 0 && v1 > this->m_numVertexs && v2 < 0 && v2 > this->m_numVertexs)
	{
		cerr<<"边的位置参数错误,请检查! "<<endl;
		return false;
	}
	else
	{
		Edge<DistType> *pmove = m_pVertexTable[v1].padjEdge;
		if (pmove == NULL)//如果顶点v1没有邻边
		{ //建立顶点v1的第一个邻边(该邻边指明了目的顶点)
			m_pVertexTable[v1].padjEdge = new Edge<DistType>(v2, weight);
			m_nnumEdges++;//图中边的数目
			return true;
		}else//如果有邻边
		{
			while (pmove->m_pnext)
			{
				pmove = pmove->m_pnext;
			}
				pmove->m_pnext = new Edge<DistType>(v2, weight);
				m_nnumEdges++;//图中边的数目
				return true;
		}
	}
}


template<class NameType, class DistType>
void Graph<NameType, DistType>::Dijkstra(int v, DistType *shPath)
{
	int num =GetNumVertexs();
	int *visited = new int[num];
	for (int i=0; i < num; i++)
	{//初始化
		visited[i] = 0;//未访问
		shPath[i] = this->GetWeight(v, i);//顶点v(当前中间点)到各个相邻顶点的边权值,其他情况返回无穷大
	}

	visited[v] = 1;//第v个顶点初始化为被访问,并以他为中点点开始找最短路径

	for (int i = 1; i < num; i++)
	{
		DistType min = this->m_Infinity;
		int u=0;
		
		//寻找新的中间点u,依据就是数组中权值最小的那个点的位置(且没被访问过)
		for (int j=0; j < num; j++)
		{   
			if (!visited[j])
			{
				if (shPath[j]<min)
				{
					min = shPath[j];//获得当前shPath数组中的最小边权重
					u = j;//用u来记录获取最小值时的顶点位置,即新的中间点
				}
			}
		}

		visited[u] = 1;//已经确定的最短路径

		//以u为中间点寻找顶点v到顶点w的最短路径
		for (int w=0; w < num; w++)
		{  
			DistType weight = this->GetWeight(u, w);//顶点u(当前中间点)到各个相邻顶点的边权值,其他情况返回无穷大
			if (!visited[w] && weight != this->m_Infinity )
			{
				if ( shPath[u]+weight < shPath[w] )
				{
					shPath[w] = shPath[u] + weight;//更新顶点v到w的最短路径值
				}
			}
		}
	}
	delete[] visited;
}



//获得顶点v1的邻点v2后的邻点
template<class NameType, class DistType> 
int Graph<NameType, DistType>::GetNext(int v1, int v2)
{
	if (-1 != v1)
	{
		Edge<DistType> *pmove = this->m_pVertexTable[v1].padjEdge;
		while (NULL != pmove->m_pnext)
		{
			if (pmove->m_nposTable==v2)
			{
				return pmove->m_pnext->m_nposTable;
			}
			pmove = pmove->m_pnext;
		}        
	}
	return -1;
}

//从第v个顶点开始深度遍历
template<class NameType, class DistType> 
void Graph<NameType, DistType>::DFS(int v, int *visited)
{
	cout << "->" << this->GetVertexName(v);
	visited[v] = 1;
	int firstVertex = this->GetFirst(v);//获得顶点v的第一个相邻顶点,若没有则返回-1
	while (-1 != firstVertex)
	{
		if (!visited[firstVertex])//如果没有访问过
		{
			cout << "->" << this->GetWeight(v, firstVertex);//获得顶点v及其邻点firstVertex之间的权值
			DFS(firstVertex, visited);
		}
		firstVertex = this->GetNext(v, firstVertex);//获得顶点v的邻点firstVertex后的邻点,如果没有就返回-1
	}
}

template<class NameType, class DistType> 
void Graph<NameType, DistType>::DFS()
{
	int *visited = new int[this->m_numVertexs];
	for (int i=0; i<this->m_numVertexs; i++)
	{
		visited[i] = 0;
	}
	cout << "head";
	DFS(0, visited);//从第一个顶点开始遍历
	cout << "--->end";
}

template<class NameType, class DistType> 
void Graph<NameType, DistType>::BFS()
{
	int *visited = new int[this->m_numVertexs];
	for (int i=0; i<this->m_numVertexs; i++)
	{
		visited[i] = 0;
	}
	cout << "head";
	BFS(0, visited);//从第一个顶点开始遍历
	cout << "--->end";
}

//从第v个顶点开始广度遍历
template<class NameType, class DistType> 
void Graph<NameType, DistType>::BFS(int v, int *visited)
{
	cout << "->" << this->GetVertexName(v);
	visited[v]=1;
	queue<int> que;//=new queue<int>[this->GetNumVertexs()];
	que.push(v);//进队(队列的末端)
	while (!que.empty())
	{
		v=que.front();//出队首元素
		que.pop();//删除队首元素
		int firstvertex=GetFirst(v);
		while(firstvertex != -1)
		{
			if (!visited[firstvertex])
			{
				cout << "->" << this->GetWeight(v, firstvertex);//获得顶点v及其邻点firstVertex之间的权值
				que.push(firstvertex);
				visited[firstvertex]=1;
				cout << "->" << this->GetVertexName(firstvertex);
			}
			firstvertex=GetNext(v,firstvertex);
		}
	}
}

//获得在顶点集中的位置为v的顶点的名字
template<class NameType, class DistType> 
NameType Graph<NameType, DistType>::GetVertexName(int v)
{
	if (v<0 || v>=this->m_numVertexs)
	{
		cerr << "查找的顶点位置参数有误,请检查!" <<endl;
		exit(1);
	}
	return m_pVertexTable[v].m_vertexName;

}

//获得顶点v的第一个相邻顶点,如果没有就返回-1
template<class NameType, class DistType> 
int Graph<NameType, DistType>::GetFirst(int v)
{
	if (v<0 || v>=this->m_numVertexs)
	{
		return -1;
	}
	Edge<DistType> *ptemp = this->m_pVertexTable[v].padjEdge;
	return m_pVertexTable[v].padjEdge ? m_pVertexTable[v].padjEdge->m_nposTable : -1;
}






template<class NameType, class DistType> 
Edge<DistType>* Graph<NameType, DistType>::GetMin(int v, int *visited)
{
	Edge<DistType> *pmove = this->m_pVertexTable[v].padjEdge; 
	Edge<DistType> *ptemp = new Edge<DistType>(0, this->m_Infinity);
	Edge<DistType> *pmin = ptemp;
	while (pmove)
	{
		if (!visited[pmove->m_nposTable] && pmin->m_distWeight>pmove->m_distWeight){
			pmin = pmove;
		}
		pmove = pmove->m_pnext;
	}
	if (pmin == ptemp)
	{
		delete ptemp;
		return NULL;
	}
	delete ptemp;
	return pmin;
}

template<class NameType, class DistType> 
void Graph<NameType, DistType>::Prim(Graph<NameType, DistType> &graphprim)
{ 
	int *nodeVertex = new int[this->m_numVertexs];    //用来存储被访问过的顶点
	int *visited = new int[this->m_numVertexs];//设置顶点被访问过与否
	int count = 0;
	Edge<DistType> *ptemp1;
	Edge<DistType> *ptemp2 = new Edge<DistType>(0, this->m_Infinity);
	Edge<DistType> *pmin;
	int min=0;
	//初始化最小生成树
	for (int i=0; i<this->m_numVertexs; i++)
	{
		graphprim.InsertVertex(this->m_pVertexTable[i].m_vertexName);
		nodeVertex[i] = 0;
		visited[i] = 0;
	}
	visited[0] = 1;//从第一个顶点开始,并标记为以访问
	while(++count < this->m_numVertexs)
	{
		pmin = ptemp2;
		pmin->m_distWeight = this->m_Infinity;

		//获得已访问顶点和未访问顶点之间的最小权值
		for (int i=0; i<count; i++){
			ptemp1 = GetMin(nodeVertex[i], visited);
			if (NULL == ptemp1)
			{
				continue;
			}
			if (pmin->m_distWeight > ptemp1->m_distWeight)
			{
				pmin = ptemp1;
				min = nodeVertex[i];            
			}
		}

		nodeVertex[count] = pmin->m_nposTable;
		visited[nodeVertex[count]] = 1;
		graphprim.InsertEdge(pmin->m_nposTable, min, pmin->m_distWeight);
		graphprim.InsertEdge(min, pmin->m_nposTable, pmin->m_distWeight);
	}

	delete ptemp2;
	delete[] nodeVertex;
	delete[] visited;
}


2,主程序代码如下:

// ConsoleAppMyGraph.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Graph.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	
	Graph<char *, int> graph(7);
	char *vertex[7] = {"【地大】", "【武大】", "【华科】", "【交大】", "【北大】", "【清华】", "【复旦】"};//顶点集
	for (int i=0; i<7; i++)
	{
		graph.InsertVertex(vertex[i]);
	}
	cout<<"一,图的初始化(邻结表存储):======================================"<<endl;
	graph.PrintGraph();
	cout<<"图中顶点的数目:"<<graph.GetNumVertexs()<<endl;
	cout <<endl;


	int edge[][3] = {{0, 1, 43}/*地大到武大的距离*/, {0, 2, 12}, {1, 2, 38}, {2, 3 ,1325},
	{3, 6, 55},{4, 5, 34}, {4, 6, 248},{0,3,400},{2,6,314},{2,4,37}};    //分配距离 
	int len=sizeof(edge)/sizeof(edge[0]);
	for (int i=0; i < len; i++)
	{
		graph.InsertEdge(edge[i][0], edge[i][1], edge[i][2]);
		graph.InsertEdge(edge[i][1], edge[i][0], edge[i][2]);
	}
	cout<<"二,添加边后的图(无向图):=================================="<<endl;
	graph.PrintGraph();
	cout<<"图中边的数目(实际上是所示边数的两倍,因为是双向的):"<<graph.GetNumEdges()<<endl;
	cout <<endl;


	cout<<"三,Dijkstra法最短路径为:=========================="<<endl;
	int shortestPath[7];//存储Dijkstra算法最短路径值
	graph.Dijkstra(0, shortestPath);
	for (int i=0; i<7; i++)
	{
		cout << graph.GetVertexValue(0) << "--->" << graph.GetVertexValue(i) 
			<< ":   " << shortestPath[i] <<endl;
	}
	cout<<endl;


	cout<<"四,图的遍历:=========================="<<endl;
	cout<<"1,DFS深度优先遍历结果:"<<endl;
	graph.DFS();
	cout<<endl<<endl;
	cout<<"2,BFS广度优先遍历结果:"<<endl;
	graph.BFS();
	cout<<endl<<endl;


	cout<<"五,最小生成生成树:================================="<<endl;
	Graph<char *, int> graphPrim;
	graph.Prim(graphPrim);
	cout<<"使用DFS遍历:"<<endl;
	graphPrim.DFS();
	cout<<endl<<endl;
	cout<<"使用BFS遍历:"<<endl;
	graphPrim.BFS();

	system("color 0A");
	system("pause");
	return 0;
}



3,测试结果:




参考资源:

【1】《算法导论》

【2】《百度文库》

【3】《维基百科》

【4】https://en.wikipedia.org/wiki/Kruskal%27s_algorithm

【5】https://en.wikipedia.org/wiki/Prim%27s_algorithm

【6】http://baike.baidu.com/linkurl=tHoWD0_Xcu_fSMMoQgLmwh_0nR1Uk0xfYRhd8zgVYSX8DMsHPSXRsQZhgvw7SL9NyHDrQkU7j7B80uusAZbl4PzSGZzJwxqHba_FJ7jAkApSmLUjq2PswoytLdvZpL7nWoUCR4jJp_MxGyGA06YQKf5WU6sHZNBbUePG6NiytO

【7】http://blog.csdn.net/todd911/article/details/9219937

【8】http://blog.chinaunix.net/uid-25324849-id-2182922.html

【9】http://www.cnblogs.com/rollenholt/archive/2012/04/09/2439055.html



注:

本文部分文字学习并copy自网络,代码参考并改写于《算法导论》.

如果侵犯了您的版权,请联系本人tangyibiao520@163.com,本人将及时编辑掉!



  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Prim算法是一种用于求解最小生成的经典算法,它的基本思想是从一个顶点开始,逐步扩展生成的边,直到覆盖所有的顶点。下面是Prim算法的C语言实现: ```c #include <stdio.h> #include <stdbool.h> #define INF 9999 #define V 5 int minKey(int key[], bool mstSet[]) { int min = INF, min_index; for (int v = 0; v < V; v++) { if (mstSet[v] == false && key[v] < min) { min = key[v]; min_index = v; } } return min_index; } void printMST(int parent[], int graph[V][V]) { printf("Edge \tWeight\n"); for (int i = 1; i < V; i++) { printf("%d - %d \t%d \n", parent[i], i, graph[i][parent[i]]); } } void primMST(int graph[V][V]) { int parent[V]; int key[V]; bool mstSet[V]; for (int i = 0; i < V; i++) { key[i] = INF; mstSet[i] = false; } key[0] = 0; parent[0] = -1; for (int count = 0; count < V - 1; count++) { int u = minKey(key, mstSet); mstSet[u] = true; for (int v = 0; v < V; v++) { if (graph[u][v] && mstSet[v] == false && graph[u][v] < key[v]) { parent[v] = u; key[v] = graph[u][v]; } } } printMST(parent, graph); } int main() { int graph[V][V] = { {0, 2, 0, 6, 0}, {2, 0, 3, 8, 5}, {0, 3, 0, 0, 7}, {6, 8, 0, 0, 9}, {0, 5, 7, 9, 0} }; primMST(graph); return 0; } ``` 这段代码实现了Prim算法的逻辑。首先定义了一个`minKey`函数,用于找到key值最小的顶点。然后定义了`printMST`函数,用于打印最小生成的边和权重。接着是`primMST`函数,其中初始化了key、mstSet和parent数组,并进行了主要的Prim算法逻辑。最后,在`main`函数中定义了一个的邻接矩阵,并调用`primMST`函数求解最小生成

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值