两种表示方式
-
邻接矩阵
-
邻接表
- 无向图 $|V|+2|E|$存储空间
- 有向图 出边表入边表之一 $|V|+|E|$
- 十字链表
- data域
- firstinarc指针指向第一条以该顶点为终点的边
- firstoutarc指针指向第一条以该顶点为起点的边
周游图
- Dfs 邻接表代价有向图$O(|V|+|E|)$ 无向图$O(|V|+2|E|)$ 相邻矩阵$O(|V|^2)$
- BFS 复杂度与dfs相同
拓扑排序
- 不唯一
- 基本思想,判断环路(bfs和dfs,dfs不能判断环)
- 复杂度:相邻矩阵$O(|V|^3)$,邻接表:$O(2|V|+|E|)$
最短路径问题
- 单源最短路径:给定源点s到图中其他各顶点的最短路径(Dijkstra算法-贪心)
- 每对顶点间的最短路径(Floyd-动规)
Dijkstra算法
- 要求:边权非负
- 思路:顶点分为两组,一旦确定了某点的最短路径就放入第一组,其余归为第二组;每次取能够到的最短的那条路径。
- 具体实现:每次加入第一个组时更新第二组的距离值,选取距离值最小的顶点加入第一组
- 设置length数组和pre数组
- 复杂度:没有最小堆:$O(V^2+E)$,最小堆不删除旧值:$O((|V|+|E|)log^|E|)$
Floyd
- 要求:允许边权值为负
- 每次算出从某点到某点中间顶点序号不大于K的最短路径长度,n次以后包括了所有最终的最短路径。
- 设置path数组(初始-1)和adj数组
- 复杂度:$O(n^3)$
最小生成树
- 包括G的所有顶点,边权值总和最小
- Prim算法和Kruskal算法
Prim
- 思路:贪心
- 从任意一点开始,把这个点包括在MST里,对一个点在MST中而另一个不在的边取出最小的放进MST
- 复杂度同Dijkstra
Kruskal
- 将所有边分成很多等价类,连通后就成为同一个等价类,按权值大小顺序处理每一条边,该边连接不同等价类就加到MST
- 复杂度$O(|E|log^|E|)$(堆排序时间)