连通图的生成树:
是一个极小的连通图,它含有图中全部的N个顶点,但是只足以构成一颗树的N-1条边。
必须满足三个条件:
- 图是连通图;
- 图中包含了N个结点
- 图中边的数量等于N-1条。
连通图生成树的判断:
下面4幅图中哪个是连通图的最小生成树?
满足最小生成树的三个条件的只有图2。所以图2是连通图的最小生成树。
阿里的面试题
假设目前优N个顶点,每个顶点链接的路径不一样,请你设计一个算法,快速找出能覆盖所以顶点的路径。
注意:该题并不是求两点间的最短路径,而是设计一个路线,能够覆盖所有顶点。
方案一:
11+26+20+22+18+21+24+19 = 161
方案二:
8+12+10+11+17+19+16+7=100
方案三:
8+12+10+11+16+19+16+7=99
上面三种方案中,第三种为最优解。
那么有没有一种算法能精准的算出网图的最优解呢?
方法就是最小生出树,即把连通图以最小代价生出的树,叫做最小生成树。
保存图
先把上面的图用邻接矩阵存储起来。关于邻接矩阵存图,可以看我上篇文章【图的存储】相关内容。
GhostClock:经典数据结构-图zhuanlan.zhihu.com最后得到结构为:
数据结构:
#include
创建邻接矩阵:
/*创建邻接矩阵*/
普里姆(Prim)算法
思路:
- 定义两个数组,lowcost,arjvex;arjvex用来保存顶点下标;lowcost用开保存顶点之间的权值;
- 初始化两个数组,从v0开始寻找最小生成树,默认v0是最小生成树上的第一顶点;
- 循环lowcost数组,根据权值找到顶点k;
- 更新lowcost数组;
- 循化所有顶点,找到与顶点k有关的顶点,并更新lowcost数组和arjvex数组。
注意:
更新lowcost数组与arjvex的条件
1.与顶点k之间有链接
2.当前结点j没有加入过最小生成树
3.顶点k与当前顶点j之间的权值小于顶点j与其他顶点k之间的权值,则更新。(简单说就是要比较之前存储的值要小,则更新)。
将与V0相关的V1-V8的所有顶点赋值对应的权值,并且arjvex[1~8]都赋值为0,表示都是与顶点V0相关的顶点。如下图所示:
如上图所示,这里定义两个数组【lowcost,arjvex】,数组lowcost存顶点之间的权值,数组arjvex保存相关顶点下标。
/* Prim算法生成最小生成树 */
使用并打印
printf
克鲁斯卡尔(Kruskal)算法
思路:
- 将邻接矩阵转换为数组;
- 对边表数组根据权值按照从小到大的顺序排列
- 遍历所有边,通过parent数组找到边的链接信息,避免闭环;
- 如果不存在闭环问题,则加入到最小生成树中,并且修改parent数组。
边表的定义:
/* 对边集数组Edge结构的定义 */
生成最小生成树
/* 生成最小生成树 */
工具方法
/* 交换权值以及头和尾 */
使用并打印:
printf