第六章图
6.1图的基本概念
1,定义
图
图G由顶点集V和边集E组成,记为G=(V,E),其中VG)表示图G中顶点的有限非空集:E(G)表示图G中顶点之间的关系(边)集合。
若V=(V1uV2…,Va],则用|V表示图G中顶点的个数,也称图G的阶,E={(u,v)I ueV,veV,用|E|表示图G中边的条数。
注意:线性表可以是空表,树可以是空树,但图不可以是空,即V一定是非空集
无向图
若E是无向边(简称边)的有限集合时,则图G为无向图。边是顶点的无序对,记为(v.w)或(w.v),因为(v.w)=(.v),其中v、w是顶点。可以说顶点w和顶点v互为邻接点。边(v,w)依附于顶点w和v,或者说边(r.w)和顶点v、w相关联。
有向图
若E是有向边(也称弧)的有限集合时,则图G为有向图。弧是顶点的有序对,记为<v.w>,其中r、w是顶点,v称为弧尾,w称为弧头,<v.w>称为从顶点v到项点w的弧,也称v邻接到w,或w邻接自v。<v,w>!= <w,v>
简单图
①不存在重复边;②不存在顶点到自身的边
多重图
图G中某两个结点之间的边数多于一条,又允许顶点通过同一条边和自己关联,则G为多重图
定点的度
对于无向图:顶点v的度是指依附于该顶点的边的条数,记为TD(v)。
对于有向图:
入度是以顶点v为终点的有向边的数目,记为ID(v);
出度是以顶点v为起点的有向边的数目,记为OD(v)。
顶点v的度等于其入度和出度之和,即TD(v)=ID(v)+OD(V)。
2,顶点到顶点的关系
.路径—-顶点vp到顶点va之间的一条路径是指顶点序列
·回路一一第一个顶点和最后一个顶点相同的路径称为回路或环
·简单路径一一在路径序列中,顶点不重复出现的路径称为简单路径。
·简单回路一一除第一个顶点和最后一个顶点外,其余项点不重复出现的回路称为简单回路。
·路径长度——路径上边的数目
·点到点的距离——从顶点u出发到顶点v的最短路径若存在,则此路径的长度称为从u到v的距离。若从u到v根本不存在路径,则记该距离为无穷(oo)
·无向图中,若从顶点v到顶点w有路径存在,则称v和w是连通的
·有向图中,若从顶点v到顶点w和从顶点w到顶点v之间都有路径,则称这两个顶点是强连通的
若图G中任意两个顶点都是连通的,则称图G为连通图,否则称为非连通图。
常见考点:
对于n个顶点的无向图G,
若G是连通图,则最少有n-1条边
若G是非连通图,则最多可能有C2,n-1条边
若图中任何一对顶点都是强连通的,则称此图为强连通图。
常见考点:
对于n个顶点的有向图G,
若G是强连通图,则最少有n条边(形成回路)。
3,图的局部
1,子图
设有两个图G=(V,E)和G’=(V’,E’),若V‘是V的子集,且E‘是E的子集,则称G’是G的子图。
若有满足V(G’)=V(G)的子图G’,则称其为G的生成子图
2,连通分量
无向图中的极大连通子图称为连通分量。
子图必须连通,且包含尽可能多的顶点和边。
3,强连通分量
有向图中的极大强连通子图称为有向图的强连通分量
子图必须强连通,同时保留尽可能多的边。
4,连通无向图的生成树
连通图的生成树是包含图中全部顶点的一个极小连通子图。
边尽可能的少,但要保持连通。
若图中顶点数为n,则它的生成树含有n-1条边。对生成树而言,若砍去它的一条边,则会变成非连通图,若加上一条边则会形成一个回路。
5,非连通无向图的生成森林
在非连通图中,连通分量的生成树构成了非连通图的生成森林。
6,边的权,带权图/网
边的权一一在一个图中,每条边都可以标上具有某种含义的数值,该数值称为该边的权值。
带权图/网——边上带有权值的图称为带权图,也称网。
带权路径长度一一当图是带权图时,一条路径上所有边的权值之和,称为该路径的带权路径长度
4,几种特殊形态的图
无向完全图——无向图中任意两个顶点之间都存在边
有向完全图——有向图中任意两个顶点之间都存在方向相反的两条弧
边数很少的图称为稀疏图,反之称为稠密图
树——不存在回路,且连通的无向图
有向树——一个顶点的入度为0、其余顶点的入度均为1的有向图,称为有向树。
6.2图的存储及基本操作
6.2.1图的存储——邻接矩阵法(顺序存储)
·如何计算指定顶点的度、入度、出度(分无向图、有向图来考虑)?时间复杂度如何?
·如何找到与顶点相邻的边(入边、出边)?时间复杂度如何?
·如何存储带权图?
·空间复杂度——O(lV|^2),适合存储稠密图
·无向图的邻接矩阵为对称矩阵,如何压缩存储?
·设图G的邻接矩阵为A(矩阵元素为0/l),则An的元素An[]U]等于由顶点i到顶点j的长度为n的路径的数目
6.2.2图的存储——邻接表法(顺序+链式存储)
邻接表 | 邻接矩阵 | |
---|---|---|
空间复杂度 | 无向图O(|v|+2|E|);有向图O(|V|+|E|) | O(|V|^2) |
适用于 | 存储稀疏图 | 存储稠密图 |
表示方式 | 不唯一 | 唯一 |
计算度/出度/入度 | 计算有向图的度、入度不方便,其余很方便 | 必须遍历对应行或列 |
找相邻的边 | 找有向图的入边不方便,其余很方便 | 必须遍历对应行或列 |
6.2.3图的存储——十字链表(有向图)、邻接多重表(无向图)
邻接矩阵 | 邻接表 | 十字链表 | 邻接多重表 | |
---|---|---|---|---|
空间复杂度 | O(|v|^2) | 无向图O(|v| + 2|E|);有向图O(|V|+|E|) | O(|V|+|E|) | O(|V|+|E|) |
找相邻边 | 遍历对应行或列时间复杂度为O(|v|) | 找有向图的入边必须遍历整个邻接表 | 很方便 | 很方便 |
删除边或顶点 | 删除边很方便,删除顶点需要大量移动数据 | 无向图中删除边或顶点都不方便 | 很方便 | 很方便 |
适用于 | 稠密图 | 稀疏图和其他 | 只能存有向图 | 只能存无向图 |
表示方式 | 唯一 | 不唯一 | 不唯一 | 不唯一 |
6.2.4图的基本操作
·Adjacent(G,x,y):判断图G是否存在边<x,y或(x,y)。
.Neighbors(G,x):列出图G中与结点x邻接的边。
.InsertVertex(G,x):在图G中插入顶点x。DeleteVertex(G,x):从图G中删除顶点x。
.DeleteVertex(G,x):从图G中删除顶点x。
.AddEdge(G,x,y):若无向边(x,y)或有向边<x,y>不存在,则向图G中添加该边。
.RemoveEdge(G,x,y):若无向边(x,y)或有向边<x,y>存在,则从图G中删除该边。
.FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1。
.NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1。
.Get_edge_value(G,x,y):获取图G中边(x,y)或<x,y>对应的权值。
.Set_edge_value(G,x,y,v):设置图G中边(x,y)或<x,y对应的权值为v。
6.3图的遍历
6.3.1图的广度优先遍历(BFS)
类似于树的层序遍历(广度优先遍历)
1,算法要点
1.找到与一个顶点相邻的所有顶点
2.标记哪些顶点被访问过
3.需要一个辅助队列
补充:
同一个图的邻接矩阵表示方式一,因此广度优先遍历序列唯一
同一个图邻接表表示方式不峰一,因此广度优先遍历序列不维一
2,复杂度
1,空间复杂度
空间复杂度:最坏情况,辅助队列大小为O(V)
2,时间复杂度
- 邻接矩阵存储的图:
访问M|个顶点需要O(|V|)的时间
查找每个顶点的邻接点都需要O(V)的时间,而总共有|M个顶点
时间复杂度=O(|V|^2)
- 邻接表存储的图:
访问M个顶点需要O(|V|)的时间
查找各个顶点的邻接点共需要O(|E|)的时间,
时间复杂度=O(|V|+|E|)
3,广度优先生成树
由广度优先遍历确定的树。
邻接表存储的图表示方式不唯一,遍历序列、生成树也不唯一。
遍历非连通图可得广度优先生成森林。
6.3.2图的深度优先遍历
1,算法要点
递归地深入探索未被访问过的邻接点(类似于树的先根遍历的实现)
如何从一个结点找到与之邻接的其他顶点
visitod 数组防止重复访问
如何处理非连通图
2,复杂度分析
1,空间复杂度
空间复杂度:来自函数调用栈,最坏情况,递归深度为O(|V|)
空间复杂度:最好情况,O(1)
2,时间复杂度
时间复杂度=访问各结点所需时间+探索各条边所需时间
- 邻接矩阵存储的图:
访问M个顶点需要O(|V|)的时间
查找每个顶点的邻接点都需要O(V)的时间,而总共有V|个顶点
时间复杂度=O(|V|^2)
- 邻接表存储的图:
访问V个顶点需要O(|V|)的时间
查找各个顶点的邻接点共需要O(|E|)的时间,
时间复杂度=O(V|+|E|)
3,深度优先生成树
同一个图的邻接矩阵表示方式唯一,因此深度优先遍历序列唯一
同一个图邻接表表示方式不唯一,因此深度优先遍历序列不唯一
由深度优先遍历确定的树。
邻接表存储的图表示方式不唯一,深度优先遍历序列、生成树也不唯一。
深度优先遍历非连通图可得深度优先生成森林。
4,图的遍历和图的连通性
无向图
DFS/BFS函数调用次数=连通分量数
有向图
若从起始顶点到其他顶点都有路径,则只需调用1次DFS/BFS函数
对于强连通图,从任一顶点出发都只需调用1次DFS/BFS函数
6.4图的应用(上)
6.4.1最小生成树
1,最小生成树的概念
对于一个带权连通无向图G=(V,E),生成树不同,每棵树的权(即树中所有边上的权值之和)也可能不同。设R为G的所有生成树的集合,若T为R中边的权值之和最小的生成树,则T称为G的最小生成树(Minimum-Spanning-Tree,MST)。
-
最小生成树可能有多个,但边的权值之和总是唯一且最小的
-
最小生成树的边数=顶点数-1。砍掉一条则不连通,增加一条边则会出现回路
-
如果一个连通图本身就是一棵树,则其最小生成树就是它本身
-
只有连通图才有生成树,非连通图只有生成森林
2,Prim算法(普里姆算法)
从某一个顶点开始构建生成树;每次将代价最小的新顶点纳入生成树,直到所有顶点都纳入为止。
时间复杂度:O(|V|^2)
适合用于边稠密图
3,Kruskal算法(克鲁斯卡尔算法)
每次选择一条权值最小的边,使这条边的两头连通(原本已经连通的就不选)。
直到所有结点都连通。
时间复杂度:O(|E|log2lE|)
适合用于边稀疏图
6.4.2最短路径问题——BFS算法(单源最短路径,无权图)
就是对BFS的小修改,在vislt一个顶点时,修改其最短路径长度 d[]并在 path[]记录前驱结点。
其广度优先生成树的高度就代表了最短路径。
6.4.3最短路径问题——Dijkstra算法(单源最短路径,带权图,无权图)
1,辅助数组
dist[]:记录从源点v0到其他各顶点当前的最短路径长度,它的初态为:若从v0到vi有弧则dist[]为弧上的权值;否则置dist为无穷大
pathl:path门表示从源点到顶点i之间的最短路径的前驱结点
2,实现过程
1)初始化:集合S初始为{0),dist]的初始值dist[i]=arcs[O][i],i=1,2.….n-1
2)从顶点集合V-S中选出Vj,满足dist[j]=Min(dist[i]Iv.eV-S}vj就是当前求得的一条从vO出发的最短路径的终点。
3)修改从Vo出发到集合V-S上任一顶点vk可达的最短路径长度:若dist[j]+arcsfj][k]<dist[k],则更新dist[k]=dist[j]+arcsJj][k]
4)重复2)~3)操作共n-1次,直到所有的顶点都包含在S中
3,时间复杂度
时间复杂度O(|V|^2)
4,不适用于权值存在负数的情况
6.4.4最短路径问题——Floyd算法(各顶点间的最短路径,带权图,无权图)
1,实现过程
初始时,对于任意两个顶点vi和可j,若它们之间存在边,则以此边上的权值作为它们之间的最短路径长度
若它们之间不存在有向边,则以无穷大作为它们之间的最短路径长度
以后逐步尝试在原路径中加入顶点k(k=0,1,2…n-1)作为中间顶点
若增加中间顶点后,得到的路径比原来的路径长度减少了,则以此新路径代替原路径
2,时间复杂度O(|V|^3)
3,允许图中有带负权值的边,但不允许有包含带负权值的边组成的回路
4,适用于带权无向图
6.4.5有向无环图描述表达式
有向无环图:若一个有向图中不存在环,则称为有向无环图,简称DAG图(Directed Acyclc Graph)
Step1:把各个操作数不重复地排成一排
Step 2:标出各个运算符的生效顾序(先后顺序有点出入无所谓)
Step 3:按顺序加入运算符,注意“分层”
Step4:从底向上逐层检查同层的运算符是否可以合体
6.4.6拓扑排序
1,AOV网
AOV网(Activity on Vertex NetMork.用顶点表示活动的网):
用DAG图(有向无环图)表示一个工程。顶点表示活动,有向边<V.V>表示活动V必须先于活动V,进行
2,拓扑排序
拓扑排序:在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序:
①每个顶点出现且只出现一次。
②若顶点A在序列中排在顶点B的前面,则在图中不存在从顶点B到顶点A的路径。
或定义为:拓扑排序是对有向无环图的顶点的一种排序,它使得若存在一条从顶点A到顶点B的路径,则在排序中顶点B出现在顶点A的后面。每个AOV网都有一个或多个拓扑排序序列。
拓扑排序的实现:
①从AOV网中选择一个没有前驱(入度为0)的顶点并输出。
②从网中删除该顶点和所有以它为起点的有向边。
③重复①和②直到当前的AOV网为空或当前网中不存在无前驱的顶点为止。
3,逆拓扑排序
对一个AOV网,如果采用下列步骤进行排序,则称之为逆拓扑排序:
①从AOV网中选择一个没有后继(出度为0)的顶点并输出。
②从网中删除该顶点和所有以它为终点的有向边。
③重复①和2直到当前的AOV网为空。
4,另一种方式实现
用DFS实现拓扑排序/逆拓扑排序
5,性质
拓扑排序、逆拓扑排序序列可能不唯一
若图中有环,则不存在拓扑排序序列/逆拓扑排序序列
6.4.7关键路径
1,AOE网
在带权有向图中,以顶点表示事件,以有向边表示活动,以边上的权值表示完成该活动的开销(如
完成活动所需的时间),称之为用边表示活动的网络,简称AOE网(Activity On Edge NetWork)。
AOE网具有以下两个性质:
①只有在某顶点所代表的事件发生后,从该顶点出发的各有向边所代表的活动才能开始;
②只有在进入某顶点的各有向边所代表的活动都已结束时,该顶点所代表的事件才能发生。
另外,有些活动是可以并行进行的
相关概念:
在AOE网中仅有一个入度为0的顶点,称为开始顶点(源点),它表示整个工程的开始;
也仅有一个出度为0的顶点,称为结束顶点(汇点),它表示整个工程的结束。
从源点到汇点的有向路径可能有多条,所有路径中,具有最大路径长度的路径称为关键路径,而把关键路径上的活动称为关键活动。
完成整个工程的最短时间就是关键路径的长度,若关键活动不能按时完成,则整个工程的完成时间就会延长
活动a的最早开始时间e(l)一一指该活动弧的起点所表示的事件的最早发生时间
活动a,的最迟开始时间4(i)一-它是指该活动弧的终点所表示事件的最迟发生时间与该活动所需时间之差。
活动a的时间余量d(i)=l(i)-e(i)),表示在不增加完成整个工程所需总时间的情况下,活动a可以拖延的时间
若一个活动的时间余量为零,则说明该活动必须要如期完成,d(()=0即/(i)=c())的活动a是关键活动
由关键活动组成的路径就是关键路径
2,求解方法
①求所有事件的最早发生时间ve()
②求所有事件的最迟发生时间vl()
③求所有活动的最早发生时间e()
④求所有活动的最迟发生时间I()
⑤求所有活动的时间余量d()
d(k)=0的活动就是关键活动,由关键活动可得关键路径
3,关键活动、关键路径的特性
若关键活动耗时增加,则整个工程的工期将增长
缩短关键活动的时间,可以缩短整个工程的工期
当缩短到一定程度时,关键活动可能会变成非关键活动
可能有多条关键路径,只提高一条关键路径上的关键活动速度并不能缩短整个工程的工期,只有加快那些包括
在所有关键路径上的关键活动才能达到缩短工期的目的。