数据结构——图

301 阅读3分钟

「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战

前端能够用得到的数据存储结构之四:图

概念

  • 无向图 < 每条边都没有方向 >
    • 标记方式 (v1, v2) or (v2, v1)
    • 无序对
  • 有向图 < 每条边都有方向 >
    • 弧:有向图的边
    • 标记方式 <v1, v2>
      • v1:弧尾
      • v2:弧头
    • 有序对
  • 节点的度(关联边数 TD(v))
    • (所有节点)度数之和 = 2 * 边数
    • 有向图中的度
      • 入度 ID(v)【 进来的边数 】
      • 出度 OD(v)【 发出的边数 】
      • ID(v) = OD(v)

数据存储

  • 顺序存储【 邻接矩阵 + 边集数组】
  • 链式存储【 邻接表 + 链式前向星 + 十字链表 + 邻接多重表 】

邻接矩阵

  • 一维数组(节点信息)
  • 二维数组(节点之间邻接关系)
  • 有向图邻接矩阵【 对称 && 唯一 】
  • 无向图邻接矩阵【 不一定对称 】
  • 存储步骤
    • 输入节点+边数
    • 依此输入节点信息到节点数组中
    • 初始化邻接矩阵【 图-0 +++ 网-∞ 】
    • 依次输入(所有)边的节点(v1 + v2)【 网 ? 输入边的权值 】
  • 优势:
    • 快速判断节点间是否有边【 时间复杂度O(1) 】
      • 图【 1-有边 +++ 0-无边 】
      • 网【 ∞-无边 】
    • 便于计算节点的度【 时间复杂度O(n) 】
      • 无向图【 sum(第 i 行元素) = 节点 i 的度 】
      • 有向图【 sum(第 i 行元素) = 节点 i 的出度; sum(第 i 列元素) = 节点 i 的入度 】
  • 劣势
    • 增删节点效率较低
    • 访问所有邻接点的时间复杂度高【 第i个-第i行所有元素 O(n); 所有节点-O(n^2) 】
    • 空间复杂度高【 O(n^2) 】

链式存储

  • 边集数组【 边的起点 + 终点;网:起点 + 终点 + 权值域 】
  • 邻接表
    • 数据结构:
      • 节点:【 节点信息 data + 指向第一个邻接点的指针 first 】
      • 邻接点:【 邻接点下标 v + 指向下一个邻接点的指针 next ( 网 ? + 权值域 w ) 】
    • 无向图
      • n 个节点 + e 条边 => 节点表(n)+ 邻接表(2e)
      • 节点的度 = 节点后单链表中的节点上
    • 有向图(出弧)
      • n 个节点 + e 条边 => 节点表(n)+ 邻接表(e)
      • 节点的出度 = 节点后单链表中的节点上
    • 有向图逆邻接表(入弧)
      • n 个节点 + e 条边 => 节点表(n)+ 邻接表(e)
      • 节点的入度 = 节点后单链表中的节点上
    • 存储步骤
      • 输入节点数 + 边数
      • 依次输入节点信息
      • 依次输入边的节点 (网 ? + 权值)
    • 优势:
      • 增删节点较方便
      • 访问所有邻接点方便【 时间复杂度O(n+e) 】
      • 空间复杂度低【 稀疏图-邻接表 O(n+e); 稠密图-邻接矩阵 O(n^2) 】
    • 劣势:
      • 不方便检查节点间有无边(+遍历节点后的邻接点链表)
      • 不方便计算各节点的度(有向图邻接表-不易求入度;有向图逆邻接表-不易求出度;其他为节点后单链表中的节点数)
  • 链式前向星
    • 采用静态链表存储方式
    • 边集数组 + 邻接表
    • 快速访问节点的所有邻接点
    • 存储结构
      • 边集数组【 edge[] (edge[i]- 第 i 条边) 】
      • 头节点数组【 head[] (head[i]- 以 i 为起点的第一条边的下标) 】
  • 十字链表( 略 )
  • 邻接多重表( 略 )

掌握以上可以更好地理解 echarts、g6 等图表插件中关系图等展现原理