forked from krahets/hello-algo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(go/graph): add go code for graph_dfs/bfs (krahets#372)
* feat(vertex): add a vertex pkg * feat(graph): add graph_bfs in go * feat(graph): add graph_dfs in go * fix(graph): fix comment * fix(graph): fix graph_adj_list * fix(go/graph): fix graph_adjacency * fix(c): gitignore * feat(graph): print order adjList graph * fix(graph): remove order print * Update graph_adjacency_list_test.go * Update .gitignore * Update .gitignore --------- Co-authored-by: Yudong Jin <[email protected]>
- Loading branch information
Showing
8 changed files
with
224 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// File: graph_bfs.go | ||
// Created Time: 2023-02-18 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_graph | ||
|
||
import ( | ||
. "github.com/krahets/hello-algo/pkg" | ||
) | ||
|
||
/* 广度优先遍历 BFS */ | ||
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点 | ||
func graphBFS(g *graphAdjList, startVet Vertex) []Vertex { | ||
// 顶点遍历序列 | ||
res := make([]Vertex, 0) | ||
// 哈希表,用于记录已被访问过的顶点 | ||
visited := make(map[Vertex]struct{}) | ||
visited[startVet] = struct{}{} | ||
// 队列用于实现 BFS, 使用切片模拟队列 | ||
queue := make([]Vertex, 0) | ||
queue = append(queue, startVet) | ||
// 以顶点 vet 为起点,循环直至访问完所有顶点 | ||
for len(queue) > 0 { | ||
// 队首顶点出队 | ||
vet := queue[0] | ||
queue = queue[1:] | ||
// 记录访问顶点 | ||
res = append(res, vet) | ||
// 遍历该顶点的所有邻接顶点 | ||
for _, adjVet := range g.adjList[vet] { | ||
_, isExist := visited[adjVet] | ||
// 只入队未访问的顶点 | ||
if !isExist { | ||
queue = append(queue, adjVet) | ||
visited[adjVet] = struct{}{} | ||
} | ||
} | ||
} | ||
// 返回顶点遍历序列 | ||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// File: graph_bfs_test.go | ||
// Created Time: 2023-02-18 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_graph | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
. "github.com/krahets/hello-algo/pkg" | ||
) | ||
|
||
func TestGraphBFS(t *testing.T) { | ||
/* 初始化无向图 */ | ||
vets := ValsToVets([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) | ||
edges := [][]Vertex{ | ||
{vets[0], vets[1]}, {vets[0], vets[3]}, {vets[1], vets[2]}, {vets[1], vets[4]}, | ||
{vets[2], vets[5]}, {vets[3], vets[4]}, {vets[3], vets[6]}, {vets[4], vets[5]}, | ||
{vets[4], vets[7]}, {vets[5], vets[8]}, {vets[6], vets[7]}, {vets[7], vets[8]}} | ||
graph := newGraphAdjList(edges) | ||
fmt.Println("初始化后,图为:") | ||
graph.print() | ||
|
||
/* 广度优先遍历 BFS */ | ||
res := graphBFS(graph, vets[0]) | ||
fmt.Println("广度优先遍历(BFS)顶点序列为:") | ||
PrintSlice(VetsToVals(res)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// File: graph_dfs.go | ||
// Created Time: 2023-02-18 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_graph | ||
|
||
import ( | ||
. "github.com/krahets/hello-algo/pkg" | ||
) | ||
|
||
/* 深度优先遍历 DFS 辅助函数 */ | ||
func dfs(g *graphAdjList, visited map[Vertex]struct{}, res *[]Vertex, vet Vertex) { | ||
// append 操作会返回新的的引用,必须让原引用重新赋值为新slice的引用 | ||
*res = append(*res, vet) | ||
visited[vet] = struct{}{} | ||
// 遍历该顶点的所有邻接顶点 | ||
for _, adjVet := range g.adjList[vet] { | ||
_, isExist := visited[adjVet] | ||
// 递归访问邻接顶点 | ||
if !isExist { | ||
dfs(g, visited, res, adjVet) | ||
} | ||
} | ||
} | ||
|
||
/* 深度优先遍历 DFS */ | ||
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点 | ||
func graphDFS(g *graphAdjList, startVet Vertex) []Vertex { | ||
// 顶点遍历序列 | ||
res := make([]Vertex, 0) | ||
// 哈希表,用于记录已被访问过的顶点 | ||
visited := make(map[Vertex]struct{}) | ||
dfs(g, visited, &res, startVet) | ||
// 返回顶点遍历序列 | ||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// File: graph_dfs_test.go | ||
// Created Time: 2023-02-18 | ||
// Author: Reanon ([email protected]) | ||
|
||
package chapter_graph | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
. "github.com/krahets/hello-algo/pkg" | ||
) | ||
|
||
func TestGraphDFS(t *testing.T) { | ||
/* 初始化无向图 */ | ||
vets := ValsToVets([]int{0, 1, 2, 3, 4, 5, 6}) | ||
edges := [][]Vertex{ | ||
{vets[0], vets[1]}, {vets[0], vets[3]}, {vets[1], vets[2]}, | ||
{vets[2], vets[5]}, {vets[4], vets[5]}, {vets[5], vets[6]}} | ||
graph := newGraphAdjList(edges) | ||
fmt.Println("初始化后,图为:") | ||
graph.print() | ||
|
||
/* 深度优先遍历 DFS */ | ||
res := graphDFS(graph, vets[0]) | ||
fmt.Println("深度优先遍历(DFS)顶点序列为:") | ||
PrintSlice(VetsToVals(res)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// File: vertex.go | ||
// Created Time: 2023-02-18 | ||
// Author: Reanon ([email protected]) | ||
|
||
package pkg | ||
|
||
// Vertex 顶点类 | ||
type Vertex struct { | ||
Val int | ||
} | ||
|
||
// NewVertex 构造方法 | ||
func NewVertex(val int) Vertex { | ||
return Vertex{ | ||
Val: val, | ||
} | ||
} | ||
|
||
// ValsToVets Generate a vertex list tree given an array | ||
func ValsToVets(vals []int) []Vertex { | ||
vets := make([]Vertex, len(vals)) | ||
for i := 0; i < len(vals); i++ { | ||
vets[i] = NewVertex(vals[i]) | ||
} | ||
return vets | ||
} | ||
|
||
// VetsToVals Serialize given vertex list to a value list | ||
func VetsToVals(vets []Vertex) []int { | ||
vals := make([]int, len(vets)) | ||
for i := range vets { | ||
vals[i] = vets[i].Val | ||
} | ||
return vals | ||
} | ||
|
||
// DeleteSliceElms 删除切片指定元素 | ||
func DeleteSliceElms[T any](a []T, elms ...T) []T { | ||
if len(a) == 0 || len(elms) == 0 { | ||
return a | ||
} | ||
// 先将元素转为 set | ||
m := make(map[any]struct{}) | ||
for _, v := range elms { | ||
m[v] = struct{}{} | ||
} | ||
// 过滤掉指定元素 | ||
res := make([]T, 0, len(a)) | ||
for _, v := range a { | ||
if _, ok := m[v]; !ok { | ||
res = append(res, v) | ||
} | ||
} | ||
return res | ||
} |