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 };
}
}
}