1、图的基本概念

树中的元素我们称为节点,图中的元素我们就叫做顶点。一个图就是一些顶点的集合,顶点有时也称为节点或者交点,这些顶点通过一系列连接,跟顶点相连接的边的条数叫做。引入边的“方向”,就是有向图,在有向图中,我们把度分为入度(In-degree)和出度(Out-degree)。例顶点2的入度为2,出度为2。每条边都有一个权重(weight)的图就是带权图。而这种带权的图被称为。此图为非连通图,若顶点0和1有边连接,则为连通图
树和链表也属于图。常见的我们的qq,微博互关,微信好友等都是图的应用。
数据结构-图的理解

2、图的存储

图的两个主要的存储方式:邻接矩阵和邻接表。

邻接列表:

在邻接列表实现中,每一个顶点会存储一个从它这里开始的边的列表。邻接列表只描述了指向外部的边。
数据结构-图的理解
当链表过长,考虑转成其他数据结构处理,如红黑树、跳表、散列表等加快查询效率,查找两个顶点之间是否存在边。

邻接矩阵:

在邻接矩阵实现中,由行和列都表示顶点,由两个顶点所决定的矩阵对应元素表示这里两个顶点是否相连、如果相连这个值表示的是相连边的权重。但是这种方式往图中添加顶点的成本非常昂贵,因为新的矩阵结果必须重新按照新的行/列创建,然后将已有的数据复制到新的矩阵中。
数据结构-图的理解
优点:存储方式简单,直接、方便计算;
缺点:浪费存储空间;

3、图的遍历

图的最基本的两种搜索算法:广度优先搜索(Breadth-First-Search)和深度优先搜索(Depth-First-Search)。
因为图中的任意顶点都可能与其他顶点相邻,所以在图的遍历中必须记录已被访问的顶点,避免重复访问,所有顶点只访问一次。

广度优先搜索:

广度优先搜索类似于树的层次遍历过程。即先查找离起始顶点最近的,然后是次近的,依次往外搜索。它需要借助一个队列来实现。

数据结构-图的理解
准备几个重要的辅助变量 visited数组、queue队列。
visited 是用来记录已经被访问的顶点,用来避免顶点被重复访问。如果顶点 v2 被访问,那相应的 visited[2]会被设置为 true。
queue 是一个队列,用来存放每一层的顶点;

思路:
1、初始时全部顶点均未被访问,visited数组初始化为0,队列中没有元素。|visited|0|0|0|0|0|0|
2、访问顶点v0,并置visited[0]的值为true,同时将v0入队。
3、将v0出队,访问v0的邻接点v2。首先判断visited[2],因为visited[2]的值为false未访问过,则访问v2。访问完将visited[2]置为true,并将v2入队。|visited|1|0|1|0|0|0|
3、同样操作访问v0邻接点v1、v3。分别将v1、v3入队列,标识设置成已访问过,|visited|1|1|1|1|0|0|
至此,v0的全部邻接点均已被访问完毕,(即第一层访问完毕),元素均已入队列,已访问标识visited[0]、visited[1]、visited[2]、visited[3]均为true已访问。
数据结构-图的理解
4、因为v0的全部邻接点均已被访问完毕,将队头元素v2出队(开始第二层的遍历),开始访问v2的所有邻接点。
数据结构-图的理解
继续访问v2邻接点v4,判断visited[4],因为其值为0,访问v4,将visited[4]置为1,并将v4入队。
数据结构-图的理解
5、v2的全部邻接点均已被访问完毕。将队头元素v1出队,开始访问v1的所有邻接点。继续访问v1邻接点v4,因为visited[4]的值为1,访问过了,不进行访问。继续访问v1邻接点v5,因为visited[5]值为0,访问v5,将visited[5]置为1,并将v5入队。
数据结构-图的理解
6、v1访问完,要访问v3了,将v3出列,开始访问v3,发现v5已经访问过了,不在访问。
7、v3的全部邻接点均已被访问完毕,开始访问v4的所有邻接点,所以将队头元素v4出队。将visited[6]值为1,并将v6入队。同理v4的所有邻接点访问完了,访问v5,将v5出列,visited[6]值为1,所以不再访问。
8、继续访问v6邻接点,v6出列,因为visited[4]、visited[5]的值文1,不进行访问。
9、此时队列为空,退出循环,全部顶点均访问完毕。

总结:从v0出发,遍历临接点,入队列。当上一个顶点v0的临接点(v2、v1、v3)全部遍历完,将要访问下一个顶点v2时,将该顶点v2出队列,将当前访问的顶点的临接点继续入队(v4),当然入队前需要通过visited数组标识判断是否已经访问过,未访问过才入队,依次重复。

相关文章: