数据结构_38

LazyPrim算法思路

LazyPrim算法思路1:
1、选择一个顶点;
2、将其所有临边加入小根堆;
3、从小根堆中选择权值最小的边,判断端点是否都被访问;
4、若边的端点都被访问,舍弃该最小边重新选择(则加入该边会形成环)否则加入该边;
5、判断联通分量是否为1:
   联通分量为1—>退出
   联通分量不为1—>重复2、3、4、5。

LazyPrim算法伪码1:

bool visited[G.vexnum] = { false };//定义顶点访问标记数组,赋初值为false
vector<VertexType> mst;				//存储最小生成树
MinHeap<EdgeType> minHeap;			//采用小根堆存储邻接边

//对于图G从s顶点开始构建最小生成树
LazyPrimMst(Graph *G, VertexType s){
	Unicoms = G.vexnum;				//初始联通分量等于顶点个数

	visit(s)
	while(Unicoms != 1){			//仅剩一个联通分量时得到最小生成树
		VertexType e = minHeap.exractMin();	//从小根堆中获取权值最小的边
		if( visited[e.w()] == true && visited[e.v()] == true )
			continue;				//若取出的最短边的两个端点都已被访问,则舍弃该最短边重复下一轮
		if( visited[e.v()] == false)
			visit(e.v());			//最短边的v结点未被访问,访问该节点
		else
			visited(e.w());			//最短边的w结点未被访问,访问该结点
		Unicoms--;					//此时有一个结点加入联通树,联通分量减一
	}
}

void visit(VertexType ver){
	visited[ver] = true;			//顶点ver标记为已访问
	Mst.push_back(ver);				//顶点ver存入最小联通树
	
	//遍历结点ver的临边
	for(e = FirstAdjVex(G, ver); e >= 0; e = NextAdjVex(G, ver, e)){
		if( !visited[e] )
			minheap.insert(*e);		//把ver相邻且不在小根堆中的边加入小根堆
	}
}

Prim算法思路2:
核心数据结构为closeDge[i]{adjvex, lowcost},其含义为:目前节点adjvex到节点i的权值最小为lowcost。最小生成树每次加入新节点后,更新整个closeDge[],再从中选取权值最小的加入最小生成树。因此Prim算法无法计算有负权重的图。
将节点分为两类:一类记为U、一类记为V,U+V等于全部节点。
1、将构建最小生成树的节点放入U中;
2、找V中到U中权值最小的节点,并将其加入U;
3、重复2,直到V中所有节点全部加入U。
Prim算法伪码2

#define MAX_VERTEX_NUM 100//节点数
struct closedge {
	VertexType adjvex;			//标记当前变量到adjvex顶点
	VRType lowcost;				//存储adjvex到当前顶点的花费
} closeDge[MAX_VERTEX_NUM];

int minimum(closedge *Dge)
{
	int Tmp;
	VRType lowcost;
	int i = 0;
	for (i; i < MAX_VERTEX_NUM; i++) {
		if (Dge[i].lowcost != 0) {
			lowcost = Dge[i].lowcost;
			Tmp = i;
			break;  
		}
	}
	for (i; i < MAX_VERTEX_NUM; i++) {
		if (Dge[i].lowcost < lowcost && Dge[i].lowcost > 0) {
			lowcost = Dge[i].lowcost;
			Tmp = i;
		}
	}
	return i;
}
//对于图G,从u顶点生成最小生成树
void miniSpanTree_Prim(MGraph G, VertexType u) {

	int k = LocateVex(G, u);//不懂
	
	for (int j = 0; j < G.vexnum; j++) {
		if (j != k)
			closeDge[j] = { u, G.arcs[k][j].adj };			//首次对closedge数组进行赋值,赋值为(初始顶点u,到u的花费)
	}
	closeDge[k].lowcost = 0;								//此时K节点(即U)已经被加入最小生成树
	for (int i = 1; i < G.vexnum; i++) {

		k = minimum(closeDge);								//选出与当前最小生成树相连的,权值最小边。
		cout << closeDge[k].adjvex << G.vexs[k];			//打印生成树的边
		closeDge[k].lowcost = 0;							//此时K节点(即U)已经被加入最小生成树

		//最小生成树加入新节点后,需要重新计算closeDge[]
		for (int j = 0; j < G.vexnum; j++) {

			//因为只加入了节点k,所以只用重新计算节点k相关边的权重
			if (G.arcs[k][j].adj < closeDge[j].lowcost)
				//如果k到j的权重小于closeDge中记录的权重,
				//则将到节点j的路径保存为k->j,并更新权重
				closeDge[j] = { G.vexs[k],G.arcs[k][j].adj };
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值