图之最小生成树prime方法c++实现

算法描述:

普利姆算法求最小生成树时候,和边数无关,只和定点的数量相关,所以适合求稠密网的最小生成树,时间复杂度为O(n*n)。

算法过程:

1.将一个图的顶点分为两部分,一部分是最小生成树中的结点(A集合),另一部分是未处理的结点(B集合)。

2.首先选择一个结点,将这个结点加入A中,然后,对集合A中的顶点遍历,找出A中顶点关联的边权值最小的那个(设为v),将此顶点从B中删除,加入集合A中。

3.递归重复步骤2,直到B集合中的结点为空,结束此过程。

4.A集合中的结点就是由Prime算法得到的最小生成树的结点,依照步骤2的结点连接这些顶点,得到的就是这个图的最小生成树。

图例:

         


不能转换图片方向。。。。。。



我建议您最好拿草稿纸出来边看边画,代码还蛮长比较费脑。

#include <bits/stdc++.h>
using namespace std;
/**
	定义数据结构体 
*/ 
const int M=100; 
typedef char Elemtype;
typedef int  ElemInt;
typedef struct Graph{
	int n;		//顶点 
	int e;		//边 
	//顶点存储	
	ElemInt  vex[M];
	//边存储 
	ElemInt  edges[M][M];
}Graph; 
/**
	查找顶点边在数组中的位置 
*/ 
int search(ElemInt vex[],ElemInt point){
	int i=0;
	while(i<M){
		if(vex[i]==point) {
			return i;
		}
		i++; 
	}
	return -1;
}
/**
	(无向图)邻接矩阵的创建 
*/ 
void CreateGraph(Graph &G){
	int l,r;
	printf("请输入顶点和边的个数\n");
	cin>>G.n>>G.e;
	printf("请输入%d条顶点\n",G.n);
	for(int i=0;i<G.n;i++)
		cin>>G.vex[i];
	//初始化矩阵(初始值) 
	for(int i=0;i<G.n;i++)
		for(int j=0;j<G.n;j++)
			if(i==j) 
				G.edges[i][j]=0;			//对角线 
			else
				G.edges[i][j]=32767;
	printf("请输入%d条边的起始和终点位置\n",G.e);
	for(int i=0;i<G.e;i++){
		int lpoint,rpoint,power;
		printf("请输入第%d条边的信息(起始点 终点 权值)\n",i+1);
		cin>>lpoint>>rpoint>>power;		//输入边的信息和权值 
		l=search(G.vex,lpoint);
		r=search(G.vex,rpoint);
		G.edges[l][r]=power;			//l--->r
		G.edges[r][l]=power;			//r--->l
	}
}
/**
	Prim算法求解最小生成树的算法 
*/
void Prim_MinTree(Graph *G){
	int min,i,j,k;		
	int adjvex[M];					//保存相关顶点下标 
	int lowcost[M];					//保存相关顶点间边的权值
	lowcost[0]=0;					//初始化边(0,0)权值为0,即v0加入生成树 
											//lowcost的值修改为0就表示该下标的顶点已经加入生成树
											
	adjvex[0]=0;					//选取定点v0为起始顶点
	for(i=1;i<G->n;i++){				//循环遍历除v0外全部顶点
		 lowcost[i]=G->edges[0][i];		//将v0顶点与其邻接点边上的权值存入数据 
		 adjvex[i]=0;				//adjvex[]初始化为顶点v0的编号0 
	} 
	
	for(i=1;i<G->n;i++){
		min=32767;				//初始化最小权值为无穷大
		j=1;
		k=0;
		while(j<G->n){				//遍历全部顶点 
			if(lowcost[j]!=0&&lowcost[j]<min){
				//如果权值w满足0<w<min
				min=lowcost[j];		//则让当前权值成为最小值
				k=j;			//若边的权值修改,将对应顶点下标存入k 
			}
			j++; 
		}
		printf("(%d,%d)",adjvex[k],k);		//打印当前顶点边中权值最小的边
		lowcost[k]=0;				//将当前边中选中的边权值置为0,表明该下标的顶点已加入生成树
		
		for(int j=1;j<G->n;j++){
				//依附顶点k的边的权值小于此前尚未加入生成树的边的权值
			if(lowcost[j]!=0&&G->edges[k][j]<lowcost[j]){
				
				//则用较小的权值替换lowcost[]中的权值
				lowcost[j]=G->edges[k][j];
				//并将adjvex[]中对应位置的元素修改为新的依附顶点
				adjvex[j]=k;	 
			} 
		} 
	}
}
int main(){
	Graph G;
	CreateGraph(G);			//创建矩阵 
	Prim_MinTree(&G);		//prime树(打印坐标) 
	
	return 0;
}



字比较多所以直接上图片了,希望我的程序您看完有所收获(不喜勿喷)

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值