Prim算法 Kruskal算法
2017-12-07 17:22
141 查看
一、Prim算法
1、要求:
(1)生成一颗连通的树
(2)生成树:包含全部顶点,V-1条边,没有回路,并且添加一条边会变成有回路
(3)权重和最小
2、过程模拟
最重要:贪心的思想,每一步都要选择权值最小的,这棵树所有跟顶点相连的边中最小的。从根节点开始,让树慢慢的长大。
过程:
从v1开始
跟v1有联系的是4,2,1,选择1,所以到了v4
现在可以选择的边有,跟v1相连接的4,2,跟v4连接的2,8,4,7,3,选择最小的2,选哪个都可以,这里选v2
现在有三个顶点了,v1有4,v2有10,v4有2,8,4,7,选择2,所以从v4连到v3
一直这样做,直到所有顶点访问完
3、思想
每次应该选择哪条边?用dist[]数组来解决。dist[]保存每个树外边的顶点vi到树顶点的集合V的最小的距离,还是用图演示。先从v1开始,树里边只有v1,所以各个顶点到树最短的距离dist[i],就是我们看到的4,1,2,还有一些没有连接上的(用无穷大表示)
接着把v4收进去,那么比如说v3到树的距离,就要更新,原来它到树的最短距离是4(就是到v1的距离),现在dist[3]变得更短了,变成了2(到v4最近)
就这样每次都更新出这个时刻,每个顶点跟树最近的距离,然后在这里距离中选取最短的那个边,把这个边上的顶点收进去
4、代码
二、Kruskal算法
1、适用情景:边稀疏的情况
区别Prim:Prim收集的是顶点,Kruskal收集的是边
2、伪代码
3、代码
1、要求:
(1)生成一颗连通的树
(2)生成树:包含全部顶点,V-1条边,没有回路,并且添加一条边会变成有回路
(3)权重和最小
2、过程模拟
最重要:贪心的思想,每一步都要选择权值最小的,这棵树所有跟顶点相连的边中最小的。从根节点开始,让树慢慢的长大。
过程:
从v1开始
跟v1有联系的是4,2,1,选择1,所以到了v4
现在可以选择的边有,跟v1相连接的4,2,跟v4连接的2,8,4,7,3,选择最小的2,选哪个都可以,这里选v2
现在有三个顶点了,v1有4,v2有10,v4有2,8,4,7,选择2,所以从v4连到v3
一直这样做,直到所有顶点访问完
3、思想
每次应该选择哪条边?用dist[]数组来解决。dist[]保存每个树外边的顶点vi到树顶点的集合V的最小的距离,还是用图演示。先从v1开始,树里边只有v1,所以各个顶点到树最短的距离dist[i],就是我们看到的4,1,2,还有一些没有连接上的(用无穷大表示)
接着把v4收进去,那么比如说v3到树的距离,就要更新,原来它到树的最短距离是4(就是到v1的距离),现在dist[3]变得更短了,变成了2(到v4最近)
就这样每次都更新出这个时刻,每个顶点跟树最近的距离,然后在这里距离中选取最短的那个边,把这个边上的顶点收进去
//不要看这个,这个是我的思路,估计只有我能看懂 从v0开始寻找 for(){ 记录所有不是树的顶点到v0的距离 } 创建一个邻接表LGraph来保存树 while(1){ //找这些跟树有关系的顶点中的最小的边 i=findMinDist_matric(); 找不到 break InsertEdge();//找到就把边插进链表里 更新权值和、顶点是否访问、已收录顶点的信息 for(遍历每一个顶点){ if(没有被访问,还有边){ if(是否因为加入了一个结点,这个顶点更近树了){ 更新dist 更新跟谁连接使他更近树了 } } } } if(所有的点都访问了){ 输出权值和 }else{ 不是树 }
4、代码
/*作用:邻接矩阵最小生成树 使用变量:用dist[]来描述树外边的顶点到树的最短距离、用 Vcount刻画收录了多少个顶点、 用parent[]描述,树外边的顶点到这棵树哪个顶点最近 更新:每次访问完一个结点,Vcount,dist[],parent都要更新*/ LGraph Prim_matric(MGraph Graph){ LGraph MST; weightType dist[MaxVertexNum],totalWeight=0; Vertex parent[MaxVertexNum],i,j; int Vcount=0;//开始没有收录任何顶点 Edge E; //初始化,从0这个顶点开始访问 for(i=0;i<Graph->nv;i++){ dist[i]=Graph->G[0][i]; parent[i]=0; } dist[0]=0;//访问过的顶点,到这棵树的距离为0 Vcount++; parent[0]=-1;//等于-1的是树根 //用邻接表来承接树的信息 //创建一个有顶点但是没有边的邻接表 MST=CreateGraph_adjacencyList(Graph->nv); E=(Edge)malloc(sizeof(struct ENode)); //一直遍历完所有的结点 while(1){ //寻找树外的结点到树的最短距离 i=findMinDist_matric(Graph,dist); if(i==ERROR) break; E->v1=parent[i]; E->v2=i;//连过去的结点 E->weight=dist[i]; InsertEdge_adjacencyList(MST,E); totalWeight+=dist[i]; dist[i]=0;//标记成访问过 Vcount++; //找是否能更新距离 for(j=0;j<Graph->nv;j++){ if(dist[j]!=0 &&Graph->G[i][j]<INFINITY){ //未被收录进树+有边 if(Graph->G[i][j]<dist[j]){ dist[j]=Graph->G[i][j]; parent[j]=i; } } } } if(Vcount<Graph->nv){ totalWeight=ERROR; printf("不是最小生成树\n"); } printf("最小树的权值和%d\n",totalWeight); return MST; } //寻找最小的权值点 Vertex findMinDist_matric(MGraph Graph,weightType dist[]){ Vertex Minv,v; weightType MinDist=INFINITY; for(v=0;v<Graph->nv;v++){ if(dist[v]!=0 &&dist[v]<MinDist){ MinDist=dist[v]; Minv=v; } } if(MinDist<INFINITY) return Minv; else return ERROR; }
二、Kruskal算法
1、适用情景:边稀疏的情况
区别Prim:Prim收集的是顶点,Kruskal收集的是边
2、伪代码
viod Kruskal(){ while(没到v-1条边 && 图中还有边){ 取出权重最小的边,从图中删除这条边(最小堆) if(这条边加入树中不构成回路,查并集判断) 加入边 else 扔掉这条边 } if(没有v-1条边) Error("不存在生成树"); }
3、代码
相关文章推荐
- 最小生成树-Prim算法和Kruskal算法
- 求最小生成树的Prim算法和Kruskal算法
- 第十三周项目一(Prim算法的验证和Kruskal算法的验证)
- 最小生成树-Prim算法和Kruskal算法
- hdu 还是畅通工程 (基础)(最小生成树)(Prim算法 && Kruskal算法)
- hdu 畅通工程再续(最小生成树)(Prim算法 && Kruskal算法)
- 【图论】最小生成树之prim算法与kruskal算法
- 最小生成树之Prim算法和Kruskal算法
- 最小生成树-Prim算法和Kruskal算法
- 最小生成树-Kruskal算法-Prim算法
- 转载:最小生成树-Prim算法和Kruskal算法
- HDU 1233.还是畅通工程【最小生成树 kruskal算法(并查集)+prim算法】【1月8】
- HDU 1233 还是畅通工程 最小生成树Kruskal算法和prim算法
- 最小生成树-Prim算法和Kruskal算法
- hdu 还是畅通工程 (基础)(最小生成树)(Prim算法 && Kruskal算法)
- hdu 畅通工程再续(最小生成树)(Prim算法 && Kruskal算法)
- 最小生成树:kruskal算法与prim算法
- 最小生成树(prim算法,Kruskal算法)c++实现
- POJ - 2485 Highways(prim算法,Kruskal算法)
- Prim算法和Kruskal算法