数据结构 | 第6章 图 概述

124 阅读5分钟

第6章 图

6.1 概述

尽管在某种程度上,第5章所介绍的树结构也可用以表示一组对象间的二元关系,但仅限于父、子节点之间。

相互之间均可能存在二元关系的一组对象,从数据结构的角度分类,属于非线性结构(non-linear structure)。此类一般性的二元关系,属于图论(Graph Theory)的研究范畴。从算法的角度对此类结构的处理策略,与上一章相仿,也是通过遍历将其转化为半线性结构,进而借助树结构已有的处理方法和技巧,最终解决问题。

  • 图:

    定义为G = (V, E),其中,集合V中的元素称作顶点(vertex);集合E中的元素分别对应于V中的某一对顶点(u, v),表示它们之间存在某种关系,故亦称作边(edge)

    从计算的需求出发,我们约定V和E均为有限集,通常将其规模分别记n = |V|和e = |E|

  • 无向图、有向图及混合图:

    无向边(undirected edge):边(u, v)所对应顶点u和v的次序无所谓。故无向边(u, v)也可记作(v, u)

    有向边(directed edge):u和v不对等。约定有向边(u, v)从u指向v,u称作起点(origin)或尾顶点(tail),v称作终点(destination)或头顶点(head)

    无向图(undirected graph,简称undigraph):E中各边均无方向

    有向图(directed graph,简称digraph):E中只含有有向边

    混合图(mixed graph):E中同时包含无向边和有向边

    image-20220708201248755.png 相对而言,有向图的通用性更强,因为无向图和混合图都可转化为有向图,如图6.1(c)所示,每条无向边(u, v)都可等效地替换为对称的一对有向边(u, v)和(v, u)。本章将主要针对有向图,介绍图结构及其算法的具体实现。

  • 度:

    在无向图中:与顶点v关联的边数,称作v的度数(degree),记作deg(v)

    在有向图中:对于有向边e = (u, v),e称作u的出边(outgoing edge)、v的入边(incoming edge)。 v的出边总数称作其出度(out-degree),记作outdeg(v);入边总数称作其入度(in-degree),记作indeg(v)

  • 简单图:

    不含任何自环(self-loop)的图称作简单图(simple graph),也是本书主要讨论的对象。

  • 通路与环路:

    通路 简单通路 环路 简单环路 有向无环图 欧拉环路 汉密尔顿环路

    image-20220708211951757.png

  • 带权网络

    各边均带有权重的图,称作带权图(weighted graph)或带权网络(weighted network),有时也简称网络(network),记作G(V, E, wt())。

  • 复杂度

    问题的输入规模应以顶点数与边数的总和(n + e)来度量

    无论顶点多少,边数都可能为0,即至少为0

    那么在包含n个顶点的图中至多有多少条边?无向:n(n - 1)/2 有向:有n(n - 1) (利用组合数算的)

    故总有 e = O(n2)O(n^2)

6.2 抽象数据类型

操作接口:

image-20220713103709538.png

Graph模板类:

 0001 using VStatus = enum { UNDISCOVERED, DISCOVERED, VISITED }; //顶点状态
 0002 using EType = enum { UNDETERMINED, TREE, CROSS, FORWARD, BACKWARD }; //边在遍历树中所属的类型
 0003 
 0004 template <typename Tv, typename Te> //顶点类型、边类型
 0005 class Graph { //图Graph模板类
 0006 private:
 0007    void reset() { //所有顶点、边的辅助信息复位
 0008       for ( Rank v = 0; v < n; v++ ) { //所有顶点的
 0009          status ( v ) = UNDISCOVERED; dTime ( v ) = fTime ( v ) = -1; //状态,时间标签
 0010          parent ( v ) = -1; priority ( v ) = INT_MAX; //(在遍历树中的)父节点,优先级数
 0011          for ( Rank u = 0; u < n; u++ ) //所有边的
 0012             if ( exists ( v, u ) ) type ( v, u ) = UNDETERMINED; //类型
 0013       }
 0014    }
 0015    void BFS ( Rank, int& ); //(连通域)广度优先搜索算法
 0016    void DFS ( Rank, int& ); //(连通域)深度优先搜索算法
 0017    void BCC ( Rank, int&, Stack<Rank>& ); //(连通域)基于DFS的双连通分量分解算法
 0018    bool TSort ( Rank, int&, Stack<Tv>* ); //(连通域)基于DFS的拓扑排序算法
 0019    template <typename PU> void PFS ( Rank, PU ); //(连通域)优先级搜索框架
 0020 public:
 0021 // 顶点
 0022    int n; //顶点总数
 0023    virtual Rank insert ( Tv const& ) = 0; //插入顶点,返回编号
 0024    virtual Tv remove ( Rank ) = 0; //删除顶点及其关联边,返回该顶点信息
 0025    virtual Tv& vertex ( Rank ) = 0; //顶点的数据(该顶点的确存在)
 0026    virtual int inDegree ( Rank ) = 0; //顶点的入度(该顶点的确存在)
 0027    virtual int outDegree ( Rank ) = 0; //顶点的出度(该顶点的确存在)
 0028    virtual Rank firstNbr ( Rank ) = 0; //顶点的首个邻接顶点
 0029    virtual Rank nextNbr ( Rank, Rank ) = 0; //顶点(相对当前邻居的)下一邻居
 0030    virtual VStatus& status ( Rank ) = 0; //顶点的状态
 0031    virtual int& dTime ( Rank ) = 0; //顶点的时间标签dTime
 0032    virtual int& fTime ( Rank ) = 0; //顶点的时间标签fTime
 0033    virtual Rank& parent ( Rank ) = 0; //顶点在遍历树中的父亲
 0034    virtual int& priority ( Rank ) = 0; //顶点在遍历树中的优先级数
 0035 // 边:这里约定,无向边均统一转化为方向互逆的一对有向边,从而将无向图视作有向图的特例
 0036    int e; //边总数
 0037    virtual bool exists ( Rank, Rank ) = 0; //边(v, u)是否存在
 0038    virtual void insert ( Te const&, int, Rank, Rank ) = 0; //在两个顶点之间插入指定权重的边
 0039    virtual Te remove ( Rank, Rank ) = 0; //删除一对顶点之间的边,返回该边信息
 0040    virtual EType & type ( Rank, Rank ) = 0; //边的类型
 0041    virtual Te& edge ( Rank, Rank ) = 0; //边的数据(该边的确存在)
 0042    virtual int& weight ( Rank, Rank ) = 0; //边(v, u)的权重
 0043 // 算法
 0044    void bfs ( Rank ); //广度优先搜索算法
 0045    void dfs ( Rank ); //深度优先搜索算法
 0046    void bcc ( Rank ); //基于DFS的双连通分量分解算法
 0047    Stack<Tv>* tSort ( Rank ); //基于DFS的拓扑排序算法
 0048    void prim ( Rank ); //最小支撑树Prim算法
 0049    void dijkstra ( Rank ); //最短路径Dijkstra算法
 0050    template <typename PU> void pfs ( Rank, PU ); //优先级搜索框架
 0051 };

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情