- 学习伪代码(这点不是硬性要求,可以直接用 Golang 实现)
- 基本定义和相关概念
- 数据结构的逻辑实现(邻接矩阵实现,邻接表实现)
- 数据结构和算法的代码实现(这里使用 Golang BFS + DFS)
- 用邻接表建立一个表,并用深度优先算法和广度优先算法来遍历途中的每个节点
Concept
图的相关基本概念来自于维基百科,从离散数学的角度解释了这些概念。图有多种变体,包括简单图、多重图、有向图、无向图等,但大体上有以下两种定义方式。
一张图 是一个二元组 ,其中 称为顶点集, 称为边集。它们亦可写成 和 。的元素是一个二元组数对,用 表示,其中 。
Reference
Data Structure
选择用邻接表来实现
type link struct {
serial int
weight int
next *link
}
// Graph -
type Graph []*link
Build
// Build -
func Build() Graph {
var (
g Graph
n, e int
p, q int
)
fmt.Scanf("%d%d", &n, &e)
for i := 0; i < n; i++ {
g = append(g, &link{
serial: i,
weight: defaultWeight,
next: nil,
})
}
for i := 0; i < e; i++ {
fmt.Scanf("%d%d", &p, &q)
node := &link{
serial: q,
weight: defaultWeight,
next: g[p].next,
}
g[p].next = node
}
return g
}
这个函数只建立了单向的连接,如果是一个无向图,应该怎样修改程序。
BFS
// Visited -
var Visited = make([]int, 100)
// DFS -
func DFS(g *Graph, v int) {
fmt.Printf("[%d]", v)
Visited[v] = 1
p := (*g)[v].next
for p != nil {
if Visited[p.serial] == 0 {
DFS(g, p.serial)
}
p = p.next
}
}
DFS
// BFS -
// Use Queue to store the sequences
func BFS(g *Graph, v int) {
fmt.Printf("[%d]", v)
var (
f, r int
Q = make([]int, 100)
)
Visited[v] = 1
p := (*g)[v].next
for (p != nil) || (f != r) {
for p != nil {
if Visited[p.serial] == 0 {
r++
Q[r] = p.serial
fmt.Printf("[%d]", p.serial)
Visited[p.serial] = 1
}
p = p.next
}
if f != r {
f++
v = Q[f]
p = (*g)[v].next
}
}
}
如果图是一个连通的图,上面的算法没有问题,考虑非连通图图的情况,应该如何修改程序。提示:如果有孤立的子图,则不会被遍历到,得想个办法找到他们,然后从一个节点开始遍历。