数据结构-图(上)-golang
继续我们的总结回顾,图的算法难度较大,理论知识也非常多,倘若是考研党的话,应掌握图的基本概念及相关性质等。我本人翻看了下教材,考虑到文字信息实在太多,所以我打算以模拟大纲形式跟大家梳理下内容,细化知识点就需要大家自行掌握记忆了。
知识框架
<span style="padding:0px;max-width:100%;font-size:16px;">图的基本概念</span>
<span style="padding:0px;max-width:100%;color:inherit;"><em style="padding:0px;max-width:100%;color:inherit;">1</em></span>图的定义
01 - 有向图
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>02 - 无向图
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>03 - 简单图
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>04 - 多重图
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>05 - 完全图
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>06 - 子图
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>07 - 连通、连通图和连通分量
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>08 - 强连通图、强连通分量
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>09 - 生成图、生成森林
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>10 - 顶点的图、入度和出度
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>11 - 边的权和网
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>12 - 稠密图、稀疏图
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>13 - 路径、路径长度和回路
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>14 - 简单路径、简单回路
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>15 - 距离
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>16 - 有向树
<span style="padding:0px;max-width:100%;font-size:16px;">图的存储及基本操作</span>
<span style="padding:0px;max-width:100%;color:inherit;"><em style="padding:0px;max-width:100%;color:inherit;">1</em></span>邻接矩阵法
<span style="padding:0px;max-width:100%;color:inherit;"><em style="padding:0px;max-width:100%;color:inherit;">2</em></span>邻接表法
<span style="padding:0px;max-width:100%;color:inherit;"><em style="padding:0px;max-width:100%;color:inherit;">3</em></span>十字链表法
<span style="padding:0px;max-width:100%;color:inherit;"><em style="padding:0px;max-width:100%;color:inherit;">4</em></span>邻接多重表
<span style="padding:0px;max-width:100%;color:inherit;"><em style="padding:0px;max-width:100%;color:inherit;">5</em></span>图的基本操作
图的基本操作是独立于图的存储结构的。而对于不同的存储方式,操作算法的具体实现会有着不同的性能。在设计具体算法的实现时,应考虑采用何种存储方式的算法效率会更高。
<pre style="margin-top:0px;margin-bottom:0px;padding:1em 1em 1em 0px;max-width:1000%;white-space:normal;">//此程序用来建立图,输出图golang实现 package main import ( "fmt" "github.com/cheekybits/genny/generic" //导入第三方包定义一个新的类型 ) type Item generic.Type //Node struct define //结点定义 type Node struct { Value Item } //Graph define //图的定义 type Graph struct { nodes []*Node //结点集合,是一个切片类型,为指向Node结构体的指针 edges map[Node][]*Node //邻接表表示的无向图 } // func (n *Node) String() string { return fmt.Sprintf("%v", n.Value) } //AddNode method //添加结点 //append用来将元素添加到切片末尾并返回结果,append(切片类型,其他的元素) func (g *Graph) AddNode(n *Node) { g.nodes = append(g.nodes, n) } //AddEdge method //增加边信息 func (g *Graph) AddEdge(u, v *Node) { //不存在图时,创建一个图 if g.edges == nil { g.edges = make(map[Node][]*Node) } g.edges[*u] = append(g.edges[*u], v) //创建u->v的边 g.edges[*v] = append(g.edges[*v], u) //无向图,也存在v->u的边 } //格式化输出图 func (g *Graph) String() { str := "" for _, node := range g.nodes { str = node.String() "->" nexts := g.edges[*node] for _, next := range nexts { str = next.String() " " } str = "\n" } fmt.Println(str) } func main() { g := Graph{} n1, n2, n3, n4, n5 := Node{Value:1}, Node{Value:2}, Node{Value:3}, Node{Value:4}, Node{Value:5} g.AddNode(&n1) g.AddNode(&n2) g.AddNode(&n3) g.AddNode(&n4) g.AddNode(&n5) g.AddEdge(&n1, &n2) g.AddEdge(&n1, &n5) g.AddEdge(&n2, &n3) g.AddEdge(&n2, &n4) g.AddEdge(&n2, &n5) g.AddEdge(&n3, &n4) g.AddEdge(&n4, &n5) g.String() }</pre>
<span style="padding:0px;max-width:100%;font-size:16px;">图的遍历</span>
<span style="padding:0px;max-width:100%;color:inherit;"><em style="padding:0px;max-width:100%;color:inherit;">1</em></span>广度优先遍历(BFS)
01 - 算法原理
广度优先搜索(Breadth-First-Search BFS)类似于二叉树的层序遍历算法。基本思想是:首先请问起始顶点v,接着由v出发,依次访问v的各个未访问过的邻接顶点W<span style="padding:0px;max-width:100%;font-size:13px;">1,</span>W<span style="padding:0px;max-width:100%;font-size:13px;">2</span>,W<span style="padding:0px;max-width:100%;font-size:13px;">3</span>........W<span style="padding:0px;max-width:100%;font-size:13px;">i</span>然后依次访问W<span style="padding:0px;max-width:100%;font-size:13px;">1</span>W<span style="padding:0px;max-width:100%;font-size:13px;">2</span>,W<span style="padding:0px;max-width:100%;font-size:13px;">3</span>........W<span style="padding:0px;max-width:100%;font-size:13px;">i</span>的所有未被访问过的邻接顶点;再从这些访问过的顶点出发,访问它们所有未被访问过的邻接顶点,直至图中所有顶点都被访问过为止。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作为始点,重复上述过程,直至图中所有顶点都被访问到为止。
换句话说,广度优先搜索遍历图的过程是以v为起始点,由近至远依次访问和ν有路径相通且路径长度为1,2,...的顶点。广度优先搜索是一种分层的查找过程,每向前走一步可能访问一批顶点,不像深度优先搜索那样有往回退的情况,因此它不是一个递归的算法。<span style="padding:0px;max-width:100%;color:rgb(255,169,0);">为了实现逐层的访问,算法必须借助一个辅助队列,以记忆正在访问的顶点的下一层顶点。</span>
<span style="padding:0px;max-width:100%;color:rgb(255,169,0);">
</span>
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>
02 - 代码实现(golang)
<pre style="margin-top:0px;margin-bottom:0px;padding:1em 1em 1em 0px;max-width:1000%;white-space:normal;">//此程序是BFS算法的golang实现,所实现的图是上一节生成的图 package graph import ( "github.com/cheekybits/genny/generic" ) type Item generic.Type //Node struct define //结点定义 type Node struct { Value Item } //Graph define //图的定义 type Graph struct { nodes []*Node //结点集合,是一个切片类型,为指向Node结构体的指针 edges map[Node][]*Node //邻接表表示的无向图 } //结点定义 type NodeQueue struct { nodes []Node } // 实现 BFS 遍历 func (g *Graph) BFS(f func(node *Node)) { // 初始化队列 q := NewNodeQueue() // 取图的第一个节点入队列 head := g.nodes[0] q.Enqueue(*head) // 标识节点是否已经被访问过 visited := make(map[*Node]bool) visited[head] = true // 遍历所有节点直到队列为空 for { if q.IsEmpty() { //队列为空直接退出 break } node := q.Dequeue() //结点出队列 visited[node] = true //将该出队列结点标记为已访问true nexts := g.edges[*node] // 将所有未访问过的邻接节点入队列 for _, next := range nexts { // 如果节点已被访问过 if visited[next] { continue } q.Enqueue(*next) visited[next] = true } // 对每个正在遍历的节点执行回调 if f != nil { f(node) } } } // 生成节点队列 func NewNodeQueue() *NodeQueue { q := NodeQueue{} q.nodes = []Node{} return &q } // 入队列 func (q *NodeQueue) Enqueue(n Node) { q.nodes = append(q.nodes, n) } // 出队列 func (q *NodeQueue) Dequeue() *Node { node := q.nodes[0] q.nodes = q.nodes[1:] return &node } // 判空 func (q *NodeQueue) IsEmpty() bool { return len(q.nodes) == 0 }</pre>
不难看出,图的广度优先搜索的过程与二叉树的层序遍历是完全一致的,这也说明了图的广度优先搜索遍历算法是二叉树的层次遍历算法的扩展。
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>
03 - 算法分析
<span style="padding:0px;max-width:100%;color:inherit;"><em style="padding:0px;max-width:100%;color:inherit;">2</em></span>深度优先遍历(DFS)
01 - 算法原理
与广度优先搜索不同,深度优先搜索(Depth-First-Search,DFS)类似于树的先序遍历。如其名称中所暗含的意思一样,这种搜索算法所遵循的搜索策略是尽可能“深”地搜索一个图。
它的基本思想如下:首先访问图中某一起始顶点ν,然后由v出发,访问与v邻接且未被访问的任一顶点W<span style="padding:0px;max-width:100%;font-size:13px;">1</span>再访问与W<span style="padding:0px;max-width:100%;font-size:13px;">1</span>邻接且未被访问的任一顶点W<span style="padding:0px;max-width:100%;font-size:13px;">2</span>......重复上述过程。当不能再继续向下访问时,依次退回到最近被访问的顶点,若它还有邻接顶点未被访问过,则从该点开始继续上述搜索过程,直至图中所有顶点均被访问过为止。
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>
02 - 算法实现
<h2 style="margin:5px;padding:0px 10px;font-size:16px;max-width:100%;border-left:5px solid rgb(0,122,170);line-height:32px;color:rgb(0,122,170);border-top-color:rgb(0,122,170);border-bottom-color:rgb(0,122,170);border-right-color:rgb(0,122,170);"/>
03 - 算法分析
到此这篇关于“数据结构-图(上)-golang”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!
您可能感兴趣的文章:
解剖Go语言map底层实现
数据结构和算法(Golang实现)(10)基础知识-算法复杂度主方法
golang 函数传多个参数_Golang中的参数传递示例详解
项目结构设置
04.Go项目布局-你如何设计项目结构
探索Golang协程实现——从v1.0开始
golang基础教程
golang 大数据平台_从数据仓库到大数据平台再到数据中台
Golang map的底层实现
SQL2Struct:一款根据sql语句自动生成golang结构体的chrome插件