图的遍历:广度优先 BFS 和深度优先 DFS
图的两种遍历方式
如题,图的广度优先和深度优先遍历。和二叉树的广度优先遍历类似都利用队列先进先出的特点,不同点在于,二叉树的BFS不需要记录节点是否遍历过,但图会有环,需要记录哪些节点是否遍历过。
考察点
- 图的数据结构
- BFS利用队列 先进先出 且节点是否遍历过
- DFS利用栈 后进先出
代码
图如下,使用邻接点表示法
/**
B -----D------F
/| /|
/ | / |
A | / |
\ | / |
\| / |
C------E
**/
package main
import (
"container/list"
"fmt"
)
func main() {
// 邻接表示
var a = map[string][]string{
"A": []string{"B", "C"},
"B": []string{"A", "C", "D",},
"C": []string{"A", "B", "D", "E"},
"D": []string{"B", "C", "E", "F"},
"E": []string{"C", "D"},
"F": []string{"D"},
}
BFS(a, "A")
fmt.Println("========")
DFS(a, "A")
// DFS(a, "D")
}
// 广度优先 利用队列
func BFS(g map[string][]string, node string) {
visited := map[string]bool{
node: true,
}
queue := list.New()
queue.PushBack(node)
for queue.Len() > 0 {
// 队列=>先进先出
front := queue.Remove(queue.Front()).(string)
fmt.Println(front)
for _, tmp := range g[front] {
if !visited[tmp] {
queue.PushBack(tmp)
// 放进队列,表示遍历过
visited[tmp] = true
}
}
}
}
// 深度优先 利用栈
// 和BFS写法上的唯一区别就是弹出去的是最后一个
func DFS(g map[string][]string, node string) {
visited := map[string]bool{
node: true,
}
stack := list.New()
stack.PushBack(node)
for stack.Len() > 0 {
// 栈=>后进先出
back := stack.Remove(stack.Back()).(string)
fmt.Println(back)
for _, tmp := range g[back] {
if !visited[tmp] {
stack.PushBack(tmp)
// 放进队列,表示遍历过
visited[tmp] = true
}
}
}
}