数据结构:七 图

1. 图的定义

定义

  • 图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E)

  • G 表示一个图,V 是图 G 中顶点的集合,E 是图 G 中边的集合

  • 线性表中我们把数据元素叫元素,树中将数据元素叫结点,在图中数据元素,我们则称之为顶点(Vertex)

  • 在图结构中,不允许没有顶点。在定义中,若 V 是顶点的集合,则强调了顶点集合 V 有穷非空

    • 线性表中可以没有数据元素,称为空表
    • 树中可以没有结点,叫做空树
  • 图中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边来表示,边集可以是空的

    • 线性表中,相邻的数据元素之间具有线性关系
    • 树结构中,相邻两层的结点具有层次关系
    •   

各种图定义

  • 无向边:若顶点 vi 到 vj 之间的边没有方向,则称这条边为无向边(Edge),用无序偶对(vi,vj)来表示

  • 有向边:若从顶点 vi 到 vj 的边有方向,则称这条边为有向边,也称为弧(Arc)

    • 用有序偶 <vi,vj> 来表示,vi 称为弧尾(Tail),vj 称为弧头(Head)

 

  • 简单图:在图中,若不存在顶点到其自身的边,且同一条边不重复出现

 

  • 无向完全图:在无向图中,如果任意两个顶点之间都存在边

  • 有向完全图:在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧

  • 有很少条边或弧的图称为稀疏图,反之称为稠密图

  • 权(Weight):与图的边或弧相关的数

    • 这些权可以表示从一个顶点到另一个顶点的距离或耗费
    • 这种带权的图通常称为网(Network)

 

图的顶点与边间关系

  • 对于无向图 G=(V,{E}),如果边(v,v')属于 E,则称顶点 v 和 v' 互为邻接点(Adjacent),即 v 和 v' 相邻接
  • 边(v,v')依附(incident)于顶点 v 和 v',或者说(v,v')与顶点 v 和 v' 相关联
  • 顶点 v 的度(Degree)是和 v 相关联的边的数目,记作 TD(v)
  • 路径的长度是路径上的边或弧的数目
  • 第一个顶点到最后一个顶点相同的路径称为回路或环(Cycle)
  • 序列中顶点不重复出现的路径称为简单路径
  • 除了第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路,称为简单回路或简单环
  •  

连通图相关术语

  • 在无向图 G 中,如果从顶点 v 到顶点 v' 有路径,则称 v 和 v' 是连通的。

  • 如果对于图中任意两个顶点 vi vj 属于 E ,vi 和 vj 都是连通的,则称 G 是连通图(Connected Graph)

  • 无向图中的极大连通子图称为连通分量

    • 要是子图
    • 子图是连通的
    • 连通子图含有极大顶点数
    • 具有极大顶点数的连通子图包含依附于这些顶点的所有边
  • 在有向图 G 中,如果对于每一对 vi vj 属于 V,vi 不等于 vj,从 vi 到 vj 和从 vj 到 vi 都存在路径,则称 G 是强连通图

  • 有向图中的极大强连通子图称做有向图的强连通分量

  • 连通图的生成树定义

    • 一个连通图的生成树是一个极小的连通子图,它含有图中全部的 n 个顶点,但只有足以构成一棵树的 n-1 条边
    • 如果一个有向图恰有一个顶点的入度为 0,其余顶点的入度为 1,则是一棵有向树
    • 一个有向树的生成森林由若干棵有向树组成,含有图中全部顶点,但只有足以构成若干棵不相交的有向树的弧

 

2. 图的抽象数据类型

ADT 图(Graph)

Data
    顶点的有穷非空集合和边的集合

Operation
    CreateGraph(*G,V,VR):按照顶点集V和边弧集VR的定义构造图G
    DestroyGraph(*G):图G存在则销毁
    LocateVex(G,u):若图G中存在顶点u,则返回图中位置
    GetVex(G,v):返回图中顶点v的值
    PutVex(G,v,value):将图G中顶点v赋值给value
    FirstAdjVex(G,*v):返回顶点v的一个邻接顶点,若顶点在G中无邻接顶点则返回空
    NextAdjVex(G,v,*w):返回顶点v相对于顶点w的下一个邻接顶点,若w是v的最后一个邻接点则返回空
    InsertVex(*G,v):在图G中增加新顶点v
    DeleteVex(*G,v):删除图G中顶点v及其相关的弧
    InsertArc(*G,v,w):在图G中添加弧<v,w>,若G是无向图,还需要添加对称弧<w,v>
    DeleteArc(*G,v,w):在图G中删除弧<v,w>,若G是无向图,则需要删除对称弧<w,v>
    DFSTraverse(G):对图G中进行深度优先遍历,在遍历过程对每个顶点调用
    HFSTraverse(G):对图G中进行广度优先遍历,在遍历过程对每个顶点调用
endADT

 

3. 图的存储结构

邻接矩阵

  • 图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组来表示图

    • 一个一维数组存储图中顶点信息
    • 一个二位数组(称为邻接矩阵)存储图中的边或弧的信息
  • 对称矩阵:n 阶矩阵的元满足 aij = aji(0 <= i, j <= n)

  •  

     

     

邻接表

  • 数组与链表相结合的存储方法称为邻接表(Adjacency List)

    • 图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过数组可以较容易地读取顶点信息,更加方便
    • 另外,对于顶点数组中,每个数据元素还需要存储指向第一个邻接点的指针,以便于查找该顶点的边信息
    • 图中每个顶点 vi 的所有邻接点构成一个线性表,由于邻接点的个数不定,所以用单链表存储,无向图称为顶点 vi 的边表,有向图则称为顶点 vi 作为弧尾的出边表
    •  

  • 无向图的邻接表结构

    • 顶点表的各个结点由 data 和 firstedge 两个域表示

      • data 是数据域,存储顶点的信息,
      • firstedge 是指针域,指向边表的第一个结点,即此顶点的第一个邻接点
    • 边表结点由 adjvex 和 next 两个域组成

      • adjvex 是邻接点域,存储某顶点的邻接点在顶点表中的下标
      • next 则存储指向边表中下一个结点的指针

 

  • 有向图的逆邻接表

    • 对每个顶点 vi 都建立一个链接为 vi 为弧头的表
    • 对带权值得网图,可在边表结点定义中再增加一个 weight 的数据域,存储权值信息即可

 

十字链表

  • 重新定义顶点表结点结构

    • firstin 表示入边表头指针,指向该顶点的入边表中第一个结点
    • firstout 表示出边表头指针,指向该顶点的出边表中的第一个结点
    •  

  • 重新定义边表结点结构

    • tailvex 是指弧起点在顶点表的下标
    • headvex 是指弧终点在顶点表中的下标
    • headlink 是指入边表指针域,指向终点相同的下一条边
    • taillink 是指边表指针域,指向起点相同的下一条边
    • 如果是网,还可以增加一个 weight 域来存储权值

 

邻接多重表

  • 重新定义边表结点结构

    • ivex 和 jvex 是与某条边依附的两个顶点在顶点表中下标
    • ilink 指向依附顶点 ivex 的下一条边
    • jlink 指向依附顶点 jvex 的下一条边

 

边集数组

  • 边集数组是由两个一维数组构成

    • 一个是存储顶点的信息
    • 另一个是存储边的信息,这个边数组每个数据元素由一条边的起点下标(begin),终点下标(end)和权(weight)组成
  • 定义的边数组结构

    • begin 是存储起点下标,end 是存储终点下标,weight 是存储权值

 

4. 图的遍历

从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这过程叫图的遍历

深度优先遍历(Depth First Search,DFS)

  • 对于连通图

    • 从图中某个顶点 v 出发,访问此顶点,然后从 v 的未被访问的邻接点出发深度优先遍历图,直至图中所有和 v 有路径相通的顶点都被访问到
  • 对于非连通图

    • 只需要对它的连通分量分别进行深度优先遍历,即在先前一个顶点进行一次深度优先遍历后,若图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止
  • 图的深度优先遍历类似树的前序遍历

  • 深度遍历更适合目标明确,以找到目标为主要目的

广度优先遍历(Breadth First Search,BFS)

  • 图的广度优先遍历就类似于树的层序遍历
  • 广度优先更适合在不断扩大遍历范围时找到相对最优解

 

5. 最小生成树

定义

  • 构建连通网的最小代价生成树

普利姆(Prim)算法

  • 以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树

克鲁斯卡尔(Kruskal)算法

 

6. 最短路径

定义

  • 非网图

    • 由于非网图它没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径
  • 网图

    • 对于网图来说,最短路径是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点

迪杰斯特拉(Dijkstra)算法

弗洛伊德(Floyd)算法

 

7. 拓扑排序

拓扑排序介绍

  • AOV 网(Activity On Vertex Network)

    • 在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称为 AOV 网
  • 拓扑序列

    • 设 G=(V, E) 是一个具有 n 个顶点的有向图,V 中的顶点序列 v1,v2,······,vn,满足若从顶点 vi 到 vj 有一条路径,则在顶点序列中顶点 vi 必在顶点 vj 之前。则我们称这样的顶点序列为一个拓扑序列
  • 拓扑排序

    • 对一个有向图构造拓扑序列的过程

    • 构造时会有两个结果

      • 如果此网的全部顶点都被输出,则说明它是不存在环(回路)的 AOV 网
      • 如果输出顶点数少了,哪怕是少了一个,也说明这个网存在环(回路),不是 AOV 网

拓扑排序算法

  • 基本思路

    • 从 AOV 网中选择一个入度为 0 的顶点输出,然后删除此顶点,并删除以此顶点为尾的弧,继续重复此步骤,直到输出全部顶点或者 AOV 网中不存在入度 0 的顶点为止

 

8. 关键路径

定义

  • AOE 网

    • 在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网,我们称之为 AOE 网(Activity On Edge Network)
    • 没有入边的顶点称为始点或源点
    • 没有出边的顶点称为终点或汇点
    • 由于一个工程,总有一个开始一个结束,所以正常情况下,AOE 网只有一个源点一个汇点
  • 路径长度:路径上各个活动所持续的时间之和

  • 关键路径:从源点到汇点具有最大长度的路径

  • 关键活动:在关键路径上的活动

关键路径算法原理

  • 找到所有活动的最早开始时间和最晚开始时间,并且比较它们,如果相等就意味着此活动是关键活动,活动间的路径为关键路径;如果不等,则就不是

  • 参数定义

    • 事件的最早发生时间 etv(earliest time of vertex)

      • 即顶点 vk 的最早发生时间
    • 事件的最晚发生时间 ltv(latest time of vertex)

      • 即顶点 vk 的最晚发生时间,也就是每个顶点对应的事件最晚需要开始的时间,超出此时间将会延误整个工期
    • 活动的最早开工时间 ete(earliest time of edge)

      • 即弧 ak 的最早发生时间
    • 活动的最晚开工时间 lte(latest time of edge)

      • 即弧 ak 的最晚发生时间,也就是不推迟工期的最晚开工时间

关键路径算法

 

posted @ 2020-09-18 16:52  颗粒成仓  阅读(503)  评论(0编辑  收藏  举报