BFS/DFS 代码实现
Graph
Undirected Graph 无向图
G = (V, E)
Graph is defined by the nodes and edges. n = |V|, m = |E|.
Representations of Graph
- Adjancency Matrix
- Space Complexity: O(n^2)
- Check if the edge (u, v) exist: O(1)
- Identifying all edges: O(n^2)
- Adjacency List
- Space Complexity: O(m+n)
- Check if an edge(u, v) exist: O(deg(u)) - the degree of u denotes the neighbors of node u
- Identifying all the edges: O(m+n)
Connectivity
An undirected graph is connected if for every pairs of nodes u and v, there is a path between u and v.
- Paths
- Circles
- Trees: 任意两个条件可以推出第三个
- The graph is connected
- No circle in the graph
- n-1 edges
- Rooted Trees
All nodes are derived from the root node. parent/ child of a node.
Graph Traversal
- Connectivity problem. If there is a path between node u and v.
- Shortest path problem. What is the shortest path beween u and v.
BFS - Breadth First Search - 广度优先搜索
Connecticity in BFS
def BFS(G, s):
layers = []
current_layer = [s]
next_layer = []
"make every vertex except s as not seen"
while "current layer not empty:"
layers.append(current_layer)
for u in current_layer:
for v in the neighborhood of u:
if v not seen:
next_layer.append(v)
"mark v as seen"
current_layer = next_Layer //当一层遍历结束,开始下一层遍历
next_layer = [] //清除
return layers
- Porperty
Let T be a BFS tree of G = (V, E), and let (u, v) be an edge of G. Then the level of u and v differ by at most 1. - Theorem
The above implementation of BFS runs in O(m + n) time if the graph is given by its adjacency list representation.- Proof
当考虑node u,和它可能的边(u,v),检测u所有的neighbors需要deg(u),对v来说是deg(u)。一共算两遍。Generally, 就是O(2m)。为啥是(m+n)不是(mn)呢?
- Proof
- Summary
- Running time of BFS depends on the graph represetation.
- Traverse all neighbors of a node u:
- Adajacency List: O(deg(u))
- Adajacency Matrix: O(n)
- Check if u and v are connected by an edge:
- Adajacency List: O(deg(u)) or O(deg(v))
- Adajacency Matrix: O(1)
- Space:
- Adajacency List: O(|V|+|E|) = O(m+n)
- Adajacency Matrix: O(|V|^2) = O(n^2)
Shortest Path in BFS
find the path with minimum edges.
Let dist[u] = shortest pat hdistance(hop distance) from s to u
def BFS(G,s):
layers = []
current_layer = [s]
next_layer = []
for all u set dist[u] = infinity
dist[s] = 0
"mark all the vertex except s as not seen"
// 这里应该要把s的neighbor加入current_layer,dist[u] = dist[s] + 1
while "current_layer not empty":
layers.append(current_layer)
for u in current_layer:
for v in the neighborhood of u:
if "v not seen":
next_layer.append(v)
"mark v as seen"
dist[v] = dist[u] + 1
current_layer = next_layer
next_layer = []
return dist //最小值就是最短路径
Transitive Closure of a graph
图里每两个node之间都有path。
def BFS_closure(G,s):
layers = []
current_layer = [s]
next_layer = []
"mark each vertex except s as not seen"
while "current_layer not empty":
layers.append(current_layer)
for u in current_layer:
for v in the neighborhood of u:
if v not seen:
next_layer.append(v)
"add edge (s,v) in the graph"
current_layer = next_layer
next_layer = []
return layers
但只增加了初始node到其他vertex之间的edge。
如果想要按层加,需要
for s inV:
BFS_closure(G,s)
但显然这样代价太高了啊?
DFS - Depth First Search - 深度优先搜索
选一个开始的节点,跟着outgoing edge一直走新的vertex,每次struck就backtrack。
def DFS(G,s):
mark vertices as unvisited
set vertices's parent as None
for u in V:
if haven't seen u:
DFS_visit(u)
return parent
def DFS_visit(u):
mark u as visited
for v in the neighborhood of u:
if haven't seen v yet:
parent[v] = u
DFS_visit(v)
- Properties
- Running time: O(m+n)
- If the graph is connected, then the DFS edges form a tree
- A graph is connected if and only if DFS results in a single tree