最小生成树—普里姆算法

普利姆算法实际上就是用一个数组存储最小生成树中的顶点,然后不断寻找这么一条边:边的一端是存在数组中的顶点,即最小生成树中的顶点,另一条边是最小生成树外的顶点,在满足这个条件下找到路径权值最小的边,并将边中原先并不在最小生成树中的顶点加入到最小生成树中,最终数组中的顶点即最小生成树的顶点数量等于图的顶点数量。

算法时间复杂度:0(n^2),适用于稠密图

#include <iostream>
#include <string>
using namespace std;

typedef struct Graph
{
	string vertex[10];//顶点
	int arc[10][10];//邻接矩阵
	int num_vertex;//顶点数量
	int num_edge;//边的数量
}Graph;

int get_location(Graph g, string s)//返回s在图中顶点数组的下标
{
	int i;
	for(i=0;i<g.num_vertex;i++)
	{
		if(s == g.vertex[i])
			return i;
	}
	return -1;
}

void create_graph(Graph &g)//创建无向图
{
	int i,j,k,w;
	string s1,s2;
	cout<<"请输入顶点数和边数:";
	cin>>g.num_vertex>>g.num_edge;
	cout<<"请输入顶点";
	for(i=0;i<g.num_vertex;i++)
		cin>>g.vertex[i];
	for(i=0;i<g.num_vertex;i++)//别忘了给邻接矩阵初始化
		for(j=0;j<g.num_vertex;j++)
			g.arc[i][j]=65535;
	cout<<"请输入边和对应的权值:"<<endl;
	for(k=0;k<g.num_edge;k++)
	{
		cin>>s1>>s2>>w;
		i = get_location(g,s1);
		j = get_location(g,s2);
		g.arc[i][j] = g.arc[j][i] = w;//邻接矩阵是对称矩阵
	}
}

void minspantree_prim(Graph g)//最小生成树
{
	cout<<"最小生成树各边为:"<<endl;
	int i;
	int lowcost[10];//lowcost数组保存相关顶点间的权值,如果其值为0,则说明该顶点加入到了最小生成树中
	int adjvex[10];//保存顶点的前一个顶点的坐标,比如a->b的权值最小,则adjvex[b]=a
	lowcost[0]=0;//初始化,将下标为0的顶点加入到最小生成树中,其实选取哪个顶点都可以
	adjvex[0]=0;//初始化
	for(i=1;i<g.num_vertex;i++)//初始化lowcost数组
	{
		lowcost[i] = g.arc[0][i];
		adjvex[i] = 0;//到g.vertex[i]顶点的最小权值路径是由g.vertex[0]到达的。这只是初始化,后面还会进行更新
	}
	for(i=1;i<g.num_vertex;i++)//这里的i不代表顶点下标,而是代表循环的次数
	{
		int min = 65535;
		int j,k;
		for(j=1;j<g.num_vertex;j++)//在那些还没有加入到最小生成树中的顶点中找到lowcost中最小权值
		{
			if(lowcost[j]!=0 && lowcost[j]<min)//前提是lowcost[j]!=0,即其没有加入到最小生成树中		
			{
				min = lowcost[j];
				k = j;
			}
		}
		cout<<g.vertex[adjvex[k]]<<"->"<<g.vertex[k]<<endl;//打印最小生成树的边
		lowcost[k]=0;//将其加入到最小生成树中
		for(j=1;j<g.num_vertex;j++)
		{
			if(lowcost[j]!=0 && g.arc[k][j]<lowcost[j])//更新lowcost的值,如果从顶点k出发的路径取值小于之前的权值,则进行更新
			{
				lowcost[j] = g.arc[k][j];
				adjvex[j]=k;//更新adjvex,代表当前到这个节点的最小全值是从顶点k出发的
			}
		}
	}
}

int main()
{
	Graph g;
	create_graph(g);
	minspantree_prim(g);
	return 0;
}



参考:http://blog.youkuaiyun.com/cxllyg/article/details/7603545

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值