• 数据结构:七 图


    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 的最晚发生时间,也就是不推迟工期的最晚开工时间

    关键路径算法

  • 相关阅读:
    从yield关键字看IEnumerable和Collection的区别
    Windows Azure Developer Guidance Map(含PDF下载)
    关于CLR内存管理一些深层次的讨论[上篇]
    关于CLR内存管理一些深层次的讨论[下篇]
    当你的博客文章的作者变成“编辑整理”,你作何感想?
    我看周马,以及3Q大战背后的社会问题
    一个完整的用于追踪数据改变的解决方案
    与VS集成的若干种代码生成解决方案[博文汇总(共8篇)]
    如果在BackgroundWorker运行过程中关闭窗体…
    采用一个自创的"验证框架"实现对数据实体的验证[扩展篇]
  • 原文地址:https://www.cnblogs.com/dc2019/p/13692191.html
Copyright © 2020-2023  润新知