赞
踩
定义:图G=(V,E) 生成树T=(U,E1)
步骤: ①判断图G是否为联通图 通过计算对图进行广度搜索得到图的联通分支数,进而判断
②初始化生成树T 从图G中任取一点加入到生成树T的顶点集合U中
③对顶点集合V和顶点集合U,任取x∈V,y∈U。当d(x,y)最小时,将x从集合V中取出放入U中
④不断重复上述过程指导顶点集合V为空
//最小生成树的Prim算法 分成两个集合U、V,求U、V中路径最小的点x,y x在U内、y在V内。不断的把点从V移动到U MGraph_ND* Prim(MGraph_ND* Basic_Graph) { if (Basic_Graph->Branch>1)return nullptr;//不连通,无最小生成树 MGraph_ND* MST = new MGraph_ND(Basic_Graph->Vertex_num); int Current_i = 0; int Current_j = 0; int Max =CountMax(MST); int min = 0; Prim_InitMST(MST); MST->Vertex[0] = Basic_Graph->Vertex[0];//放入第0号元素 Basic_Graph->Vertex[0] = -1;//取出0号元素 MST->Vertex_num++; //n个节点,n-1次循环 for (int k = 0; k < Basic_Graph->Vertex_num-1; k++) { min =Max; for (int i = 0; i < Basic_Graph->Vertex_num; i++) { //i在集合V内 if (Basic_Graph->Vertex[i] != -1) { for (int j = 0; j < Basic_Graph->Vertex_num; j++) { //j在集合U内 if (MST->Vertex[j] != -1) { if (Basic_Graph->Edge[j][i] <= min && Basic_Graph->Edge[j][i]>0) { min = Basic_Graph->Edge[j][i]; Current_i = i; Current_j = j; } } } } } Basic_Graph->Vertex[Current_i] = -1;//从集合V中取出 MST->Vertex[Current_i] = Current_i;//加入集合U MST->Edge[Current_j][Current_i] = min;//加边 MST->Edge[Current_i][Current_j] = min;//加边 MST->Vertex_num++; MST->Edge_num++; } MST->Branch = Count_Linked(); return MST; } -----Init //Prim算法要求刚开始时 U集合内 点和边均为空 void Prim_InitMST(MGraph_ND* MST) { for (int i = 0; i < MST->Vertex_num; i++) { MST->Vertex[i] = -1;//无结点 for (int j = 0; j < MST->Vertex_num; j++) { MST->Edge[i][j] = -1;//无边 } } MST->Vertex_num = 0; MST->Edge_num = 0; MST->Branch = 0; }
定义:图G=(V,E) 生成树T=(U,E1)
步骤: ①判断当前图是否为联通图
②初始化生成树T ⭐这里域Prim算法不同的是,Kruskal算法需要刚开始就确定好所有顶点位置,后续再更新边
③计算当前的联通分支数 因为生成树内没有边,所有联通分支数就是顶点数
④当生成树的联通分支数大于1时:
找出生成树内最短的边,记录顶点坐标(u,v)和长度length
如果u和v属于不同分支则将u、v划入同一集合中,并更新生成树
否则将这条边抛弃⭐(这步很重要,否则会成环)
可以使用划分等价类的形式,不断得将不同联通分支的点聚合。最终变成只有一个联通分支
//最小生成树的Kruskal算法 已初始化点 只需要找到边 MGraph_ND* Kruskal(MGraph_ND* Basic_Graph) { if (Basic_Graph->Branch > 1)return nullptr;//不连通,无最小生成树 MGraph_ND* MST = new MGraph_ND(Basic_Graph->Vertex_num); int branch = MST->Vertex_num; Set *sets[MaxSize]; Kruskal_InitMST(MST); for (int i = 0; i < MST->Vertex_num; i++) { sets[i] = new Set(i); } //连通分支数大于1 while(branch>1){ int i; int j; int Min = 1000; for (int m = 0; m < Basic_Graph->Vertex_num; m++) { for (int n = 0; n < Basic_Graph->Vertex_num; n++) { //求最小的边 if (Basic_Graph->Edge[m][n]<=Min && Basic_Graph->Edge[m][n]>0) { Min = Basic_Graph->Edge[m][n]; i = m; j = n; } } } Set* pi=sets[i]; Set* pj=sets[j]; while (pi->parent != nullptr) { pi = pi->parent; } while (pj->parent != nullptr) { pj = pj->parent; } //i和j属于不同联通分支 if (pi->tag!= pj->tag) { Basic_Graph->Edge[i][j] = -1;//从原集合中取出边 Basic_Graph->Edge[j][i] = -1; MST->Edge[i][j] = Min;//向U中放入边 MST->Edge[j][i] = Min; MST->Edge_num++; Set* parent = new Set(pi->tag>pj->tag ?pj->tag:pj->tag);//取较小的那个为tag pi->parent = parent; pj->parent = parent; cout << sets[0]; branch--; } else { Basic_Graph->Edge[i][j] = -1;//i和j属于相同联通分支,应该丢弃,否则构成回路,最终导致死循环 Basic_Graph->Edge[j][i] = -1; } } return MST; } ----Init //Prim算法要求刚开始时 U集合内 边均为空,只有空点 void Kruskal_InitMST(MGraph_ND* MST) { for (int i = 0; i < MST->Vertex_num; i++) { MST->Vertex[i] = i;//无结点 for (int j = 0; j < MST->Vertex_num; j++) { MST->Edge[i][j] = -1;//无边 } } MST->Edge_num = 0; MST->Branch = 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。