数据结构系列15之图的存储方式2

一.十字链表和邻接多重表

1.十字链表(专门优化有向图的邻接表)

核心问题:

普通邻接表存储有向图时,入边和出边分离------想查一个顶点的所有出度,直接查其邻接链表;想查所有入度,却需要遍历整个图的所有邻接链表,效率极低

​ 设计逻辑:

将有向图的每一条边设计为一个独立的节点,节点中同时记录: 起点、终点、起点的下一条出边、终点的下一条入边;同时为每个顶点维护两个指针: 出度表头 (指向该顶点的第一条出度)、 入度表头 (指向该顶点的第一条入度)

​核心优势:

出入度更方便,同时支持O(d)的出度和入度遍历,增删边时仅需修改相邻边节点的指针,无需遍历整个图,适配"频繁增删边、需要同时处理入度和出度"的有向图场景(如拓扑排序、关键路径的频繁操作)

十字链表相当于正邻接表逆邻接表的结合

但是空间利用率更高

2.邻接多重表(专门优化无向图的邻接表)

核心问题:

普通邻接表存储无向图时,同一条边被存储两次(i的链表存j,j的链表存i)------增删边时,需要同时找到并修改两个节点,操作繁琐且容易出错

​ 设计逻辑:

将无向图的每一条边设计为一个独立的节点,节点中记录: 边的两个顶点、顶点1的下一条邻接边、顶点2的下一条邻接边 ;每个顶点仅维护一个指针,指向其任意一条邻接边节点

​ 核心优势:

一条边仅存储一次,增删边时仅需操作一个边节点,修改其指针即可,适配"频繁删边、边数较多"的无向图场景

存储结构的核心选择原则(使用场景)

看"顶点数n"和"边数e"的比例,本质是"空间"和"效率"的权衡:

(1) 当e ≈ n²(稠密图):选邻接矩阵,空间浪费少,查询边快;

​(2) 当e ≈ n(稀疏图):选邻接表,空间利用率极高,遍历邻接顶点快;

​ (3)当需要频繁操作有向图的入边/出边:选十字链表;

​(4)当需要频繁增删无向图的边:选邻接多重表

二.代码

1.十字链表

1.1要点

删除:(和多重邻接表删除思想一样,重点考虑一条边两个顶点,在那两层分别找到这两个顶点)

遍历顶点 u 的 出边链,找到 <u, v> 弧,从出链摘除

​ 遍历顶点 v 的 入边链,找到 <u, v> 弧,从入链摘除

​ free(弧节点)

核心:

弧的结构定义:包含(弧尾)出度,(弧头)入度

顶点结构:序号,元素,入度/出度头节点

图头结构:定点结构,约束边,边总数

释放图时候,站在每一层顶点头出遍历删除释放,一层接着一层

在添加边时候对入度出度同时进行头插法的操作,变会构成图中十字链表结构

no编号的出度入度的计算: 站在该节点的那一层上,分别看tailNext / headNext的节点数即可

1.2代码

.h

.c

main.c

2.邻接多重表

2.1要点

删除操作:邻接多重表删除,找a,b节点,找到这个边,在释放

核心:

一条边,要找两个点;删除时,找到边,i不一定就是V1,j也不一定是V2

比如,从节点进来,V1在iLink上,就从iLink找,V1在jLink上就从jLink找; 提供找的方法 ;iLink链接的是以V1为起始(i)/终止(j)位置的下一个边

边的关系:以i为头节点往下走,以谁为节点到j

2.2代码

.h

.c

main.c

相关推荐
王老师青少年编程1 小时前
2021年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第1题)
c++·题解·真题·初赛·信奥赛·csp-s·提高组
TracyCoder1231 小时前
LeetCode Hot100(55/100)——347. 前 K 个高频元素
数据结构·算法·leetcode
IvanCodes2 小时前
八、C语言构造类型
c语言·开发语言
REDcker2 小时前
curl完整文档
c++·c·curl·服务端·后端开发
小比特_蓝光2 小时前
STL小知识点——C++
java·开发语言·c++·python
阿猿收手吧!2 小时前
【C++】格式化库:告别繁琐,拥抱高效
开发语言·c++
俩娃妈教编程2 小时前
洛谷选题:P1055 [NOIP 2008 普及组] ISBN 号码
c++·算法
悲伤小伞2 小时前
Linux_应用层自定义协议与序列化——网络计算器
linux·服务器·c语言·c++·ubuntu
!停2 小时前
数据结构二叉树—链式结构(中)
java·数据结构·算法