定义
其实跟树差不多,但是树强调的是节点(data),图则既强调节点又强调边。
分类
- 有向图(边有方向)
- 无向图(边没方向)
例如,在无向图里<j,i>和<i,j>是同一条边。在有向图里<j,i>代表从节点j指向节点i的一条边,显然<j,i>和<i,j>就不是同一条边了。
术语
度
一个顶点所关联的边的数目。
有向图另外区分入度和出度。
- 入度:以该顶点为终点的边的数目
- 出度:以该顶点为起点的边的数目
- 度:出度和入度之和
图中所有顶点度数之和等于边数的二倍。
完全图
图中每个顶点都有与其他所有顶点的连线,这意味着有向图每两个节点之间是有两条线,来回各一条。
k阶完全图有k*(k-1)/2条边
路径
路径就是顶点序列(由于一对顶点可以表示一条边,那么该序列相邻两个顶点就是一条边,整个序列就是多个边首尾相接),该序列含有的边的数目就是路径长度。
若一条路径上除了开始点和结束点可以相同(注意,是可以,但未必一定得相同)外,其余顶点均不相同,则称此路径为简单路径。
连通
在无向图G中若两个顶点之间有路径则称这两个顶点是连通的。
若无向图G中任意两个顶点都是连通的则称图G为连通图。
这里有点绕,其实就是说一个点不管经过多少路径能走到另一个点,就说这俩是连通的。
连通子图:
连通分量:指无向图G中的极大连通子图。因此连通图的连通分量只有自身一个,而非连通图有多个。
这里要对极大连通子图和极小连通子图饶舌一下:
- 极大连通子图就是连通分量。
- 极小连通子图是用最少的边实现所有的边连通。
上面说了两个顶点之间有路径则称这两个顶点是连通的,但是没说有多少路径(极大就是希望路径尽可能多)。对比看来,极大连通子图与极小连通子图相反,它要尽可能多地纳入原图的边,并且使这个图是连通的。
亦可以直接参考这篇文章讲的 图的连通
权和网
边带权的图叫做带权图,也叫做网(net)
生成树
最小生成树其实是最小权重生成树的简称
一个连通图的生成树是一个极小连通子图,其中含有图的全部顶点,和构成树的n-1条边。
强调连通图是因为要防止某些存在孤立无连接的顶点的特例
具体算法参见下方的基本运算
最小生成树和最短路的区别
最小生成树只是连通且保证边的权值之和最少,但是不保证任意两点之间是最短路径
最短路解决的问题是单源点的最短路径,它确保对于指定的点(源点)到任何其他点的距离最短。
处理最小生成树一般提到两种算法(具体内容均见后文):
- Prim
- Kruskal
两种方法结果是一样的,但是过程不太一样。
处理最短路问题一般提到两种算法(具体内容均见后文):
- Dijkstra算法
- Floyd算法
其中Floyd算法可以处理权值为负的情况
Dijkstra不可处理权值为负的情况,原因看下文
Dijkstra最短路径算法的权值不能为负及其原因
存储方法
往前想一想,学数据结构之前那些栈和队列的实现,都是围绕数组和链表两种结构实现的,图这种数据结构也不例外。
使用数组实现的叫做邻接矩阵存储方法,而使用链表实现的则是邻接表存储方法。
稠密图用邻接矩阵存储
稀疏图用邻接表存储
原因:首先明确邻接表是链表,这意味着本身存储效率就有损耗。因为有一部分空间用于表示指针域,即维护各节点之间的关系。存储效率=有用数据占用空间/总占用空间
,非零节点是有用的数据,邻接表只存储非零节点,稀疏图零节点多。稠密图类似,零节点少,采用邻接矩阵。
邻接矩阵存储方法
邻接表存储方法
基本运算
遍历
最小生成树的算法
kruskal
在原无向带权图中选择一些边构成新的图(显然也是树),选的原则是:
- 总选择权值最小的边加入作为结果的新图里
- 若选择的边与此前已选择的边会构成环则弃而选权值次小的
Prim
看这篇文章讲的Prim算法
最短路
Dijkstra与Floyd
说实话文字叙述确实抽象,我的建议是看视频,而我恰好看到了这个视频讲的挺好的:
看这个B站视频讲的
拓扑序列
性质/要求:对于对于有边或路径<i,j>则在拓扑序列中必有i在j前面
前提:图是有向图。只有有向无环图才有拓扑序,所以有向无环图又被称为拓扑图。有向有环图也可以输出拓扑序,只是输出的顶点序列是该图所有顶点的一部分。
在一个有向图中找一个拓扑序列的过程称为拓扑排序
拓扑排序的步骤是:
- 从图中选一个没有前驱(入度为0)的顶点(如果有多个则任选1个)输出
- 在图中去掉该顶点和它延伸出去的所有边
- 然后重复上述步骤
(显然由上面的1可以知道)拓扑序列可能不唯一
这时候就不得不提AOV网(Activity on Vertex Network)与AOE网(Activity On Edge)
AOV与AOE
AOV | AOE | |
---|---|---|
边表示 | 先后顺序 | 事件 |
顶点表示 | 事件 | 状态 |
边是否有权 | 否 | 是 |
AOV网是没有权值的,只是表示了事情的优先顺序,比如说上图(忽略掉边权值)可以看出来,先完成 V 1 V_1 V1才可以进行 V 2 V_2 V2和 V 3 V_3 V3表示的内容
AOE网有权值,表示完成该边代表事件所对应的代价(如所需时间),那么比如说从 V 1 V_1 V1这个状态到 V 2 V_2 V2需要完成时间 a 1 a_1 a1,耗时3小时,这就是一种可能具有的含义。
在AOE网中,状态 a i a_i ai的解锁当且仅当其所有前驱节点解锁
比如说上图只有 V 2 V_2 V2和 V 3 V_3 V3都完成了才能进行 V 4 V_4 V4
看下方的时间轴图,不用多说,立马明白关键路径(第一行)的意义
关键路径可以有多条
例如上图a1+a4+a8+a11也是
关键路径求法
显然对于某个关键事件
a
有ve(a)=vl(a)
定义是这样的:
ve(v)
是源点x
到v
所有路径的最大值,即
v l ( v ) = v e ( y ) − M A X { c ( p ) } vl(v)=ve(y)-MAX\{c(p)\} vl(v)=ve(y)−MAX{c(p)}
参考
李春葆《数据结构教程》
图的连通,连通图,连通分量,强连通分量
浅谈什么是图拓扑排序
7.1 图的定义与基本术语(这位仁兄的数据结构专栏看起来还可以啊)