转接上一篇,地址:https://blog.youkuaiyun.com/q1119823309/article/details/90703135
我的码云地址:码云地址
开始
统一:假设图没有自环边和平行边
1. 稠密图 - 邻接矩阵
对于稠密图,使用邻接矩阵来表示,用一个n*n二维数组(n个节点)来表示是否有边。
2. 稀疏图 - 邻接表
对于稀疏图,使用邻接表来表示,用链表数组来存储连接信息
3. 图的操作
- 使用深度遍历来求图的连通分量
- 使用栈进行广度优先遍历(寻路算法)
4. 最小生成树算法
- lazy prim 算法(算法复杂度 O( E log(E))
先定一个起点,记录起点并找到该点连接的所有未访问过的边放入最小堆中,找到最小边,判断是否访问过的点,是就抛弃,不是就记录该点,并将该点连接的所有未访问过的边加入最小堆中。。。直到所有点都记录完全。 - prim 算法(优化、算法复杂度O( E log(V))
优化 lazy prim 算法,将最小堆改为最小索引堆。堆中 data 存权值,index作为连接的点,若访问点连接的点的边在堆中为空或者比堆中的小就替换该点的 data 值。 - kruskal 算法(算法复杂度(O( E log(E))
把所有边都加入到最小堆中,把最小的边取出来,通过并查集判断两点是否连通,不连通则记录点和边,并将加入到并查集中,以此类推。
单源最短路径算法
松弛操作:尝试能不能从一点出发经由另外的点找到到另一点更短的路径
- Dijkstra 算法(算法复杂度O( E log(V))
前提:不能有负权边
从定义的起点开始,把点和边加入到最小索引堆中,记录该点,把连接的边都取出来判断连接的点是否被记录,记录的点丢弃,否则判断连接的点是为空则加入堆中,或者值比连接的边大则改变权值,以此类推。 - Bellman-Ford 算法(算法复杂度(O( E V ))
前提:可以有负权边但不能有负权环。(可以判断是否后负权环)
从0开始遍历 V-1 遍,每一遍都对所有边进行松弛操作,早点更小的路径并更新。遍历晚后可再进行对所有边进行一次松弛操作,如果此时有更小的路径更新则该图有负权环。
优化: 利用队列数据结构进行优化(queue-based bellman-ford算法)
扩展
- 对于有向无环图(DAG)可使用拓扑排序,算法复杂度O( V+E )
- 所有点最短路径算法,可以执行V次Dijkstra算法或者Bellman-Ford算法,也可以使用Floyed算法,处理无负权环的图,算法复杂度O(V^3)
- 最长路径算法不能有正权环,指数级的难度,无权图的问题是指数级难度的,而对于有权图不能使用Dijkstra算法。可以使用Bellman-Ford算法(将所有权值取负)
算法思想:
- 分治:归并排序;快速排序;树结构
- 贪心:选择排序;堆;Kruskal;Prim;Dijkstra
- 递归回溯:树的遍历;图的遍历
- 动态规划:Prim;Dijkstra