20230329 6.2. 图的遍历
深度优先搜索(Depth First Search, DFS)
void DFS ( Vertex V )
{
visited[ V ] = true;
for ( V 的每个邻接点 W )
if ( !visited[ W ] )
DFS( W );
}
若有N个顶点、E条边,时间复杂度是
- 用邻接表存储图,有O(N+E)
- 用邻接矩阵存储图,有O(N2)
广度优先搜索(Breadth First Search, BFS)
void BFS ( Vertex V )
{
visited[V] = true;
Enqueue(V, Q);
while(!IsEmpty(Q)){
V = Dequeue(Q);
for ( V 的每个邻接点 W )
if ( !visited[W] ) {
visited[W] = true;
Enqueue(W, Q);
}
}
}
若有N个顶点、E条边,时间复杂度是
- 用邻接表存储图,有O(N+E)
- 用邻接矩阵存储图,有O(N2)
图不连通怎么办?
- 连通:如果从V到W存在一条(无向)路径,则称V和W是连通的
- 路径:V到W的路径是一系列顶点{V, v1, v2, …, vn, W}的集合,其中任一对相邻的顶点间都有图中的边。
- 路径的长度是路径中的边数(如果带权,则是所有边的权重和)。如果V到W之间的所有顶点都不同,则称简单路径
- 回路:起点等于终点的路径
- 连通图:图中任意两顶点均连通
- 连通分量:无向图的极大连通子图
- 极大顶点数:再加1个顶点就不连通了
- 极大边数:包含子图中所有顶点相连的所有边
- 强连通:有向图中顶点V 和 W之间存在双向路 径,则称V 和 W是强连通的
- 强连通图:有向图中任意两顶点均强连通
- 强连通分量:有向图的极大强连通子图
每调用一次DFS(V),就把V所在的连通分量遍历了一遍。BFS也是一样。
代码实现
邻接矩阵
boolean[] visited;
/**
* 深度优先
*
* @param i 遍历起始节点索引
*/
public void dfs(int i) {
visited[i] = true;
Console.log(i);
// 遍历node的所有出度,也就是行非0的元素
for (int w = 0; w < edges[i].length; w++) {
if (edges[i][w] == 1 && !visited[w]) {
dfs(w);
}
}
}
/**
* 广度优先
*
* @param i 遍历起始节点索引
*/
public void bfs(int i) {
boolean[] visited = new boolean[size];
Queue<Integer> queue = new LinkedList<>();
visited[i] = true;
queue.offer(i);
Console.log(i);
while (!queue.isEmpty()) {
int v = queue.poll();
for (int w = 0; w < edges[v].length; w++) {
if (edges[v][w] == 1 && !visited[w]) {
visited[w] = true;
queue.offer(w);
Console.log(w);
}
}
}
}
邻接链表
List<Integer> visited;
/**
* 深度优先
*
* @param id 遍历起始节点索引
*/
public void dfs(int id) {
visited.add(id);
Console.log(id);
// 遍历node的所有出度,也就是行非0的元素
LinkedGraphNode node = edges[id];
while (node != null) {
if (!visited.contains(node.id)) {
dfs(node.id);
}
node = node.next;
}
}
/**
* 广度优先
*
* @param id 遍历起始节点索引
*/
public void bfs(int id) {
List<Integer> visited = ListUtil.toList();
Queue<Integer> queue = new LinkedList<>();
visited.add(id);
queue.offer(id);
Console.log(id);
while (!queue.isEmpty()) {
int v = queue.poll();
LinkedGraphNode node = edges[v];
while (node != null) {
int w = node.id;
if (!visited.contains(w)) {
visited.add(w);
queue.offer(w);
Console.log(w);
}
node = node.next;
}
}
}