「这是我参与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 的入度 】
- 快速判断节点间是否有边【 时间复杂度O(1) 】
- 劣势
- 增删节点效率较低
- 访问所有邻接点的时间复杂度高【 第i个-第i行所有元素 O(n); 所有节点-O(n^2) 】
- 空间复杂度高【 O(n^2) 】
链式存储
- 边集数组【 边的起点 + 终点;网:起点 + 终点 + 权值域 】
- 邻接表
- 数据结构:
- 节点:【 节点信息 data + 指向第一个邻接点的指针 first 】
- 邻接点:【 邻接点下标 v + 指向下一个邻接点的指针 next ( 网 ? + 权值域 w ) 】
- 无向图
- n 个节点 + e 条边 => 节点表(n)+ 邻接表
(2e) 节点的度= 节点后单链表中的节点上
- n 个节点 + e 条边 => 节点表(n)+ 邻接表
- 有向图(出弧)
- n 个节点 + e 条边 => 节点表(n)+ 邻接表
(e) 节点的出度= 节点后单链表中的节点上
- n 个节点 + e 条边 => 节点表(n)+ 邻接表
- 有向图逆邻接表(入弧)
- n 个节点 + e 条边 => 节点表(n)+ 邻接表
(e) 节点的入度= 节点后单链表中的节点上
- n 个节点 + e 条边 => 节点表(n)+ 邻接表
- 存储步骤
- 输入节点数 + 边数
- 依次输入节点信息
- 依次输入边的节点 (网 ? + 权值)
- 优势:
- 增删节点较方便
- 访问所有邻接点方便【 时间复杂度O(n+e) 】
- 空间复杂度低【 稀疏图-邻接表 O(n+e); 稠密图-邻接矩阵 O(n^2) 】
- 劣势:
- 不方便检查节点间有无边(+遍历节点后的邻接点链表)
- 不方便计算各节点的度(有向图邻接表-不易求入度;有向图逆邻接表-不易求出度;其他为节点后单链表中的节点数)
- 数据结构:
- 链式前向星
- 采用静态链表存储方式
- 边集数组 + 邻接表
- 快速访问节点的所有邻接点
- 存储结构
- 边集数组【 edge[] (edge[i]- 第 i 条边) 】
- 头节点数组【 head[] (head[i]- 以 i 为起点的第一条边的下标) 】
- 十字链表( 略 )
- 邻接多重表( 略 )
结
掌握以上可以更好地理解 echarts、g6 等图表插件中关系图等展现原理