何为图?
一种描述多对多关系的一种数据结构。更正式的定义是将图描述成有限非空顶点集+有限边集。从这个定义来看,自然是不存在空图的。
与线性表及树的区别:
- 链表(一对一),元素至多有且仅有一个前驱和一个后继;
- 树(一对多),元素至多有且仅有一个父节点和任意个子节点。其实树可以看作一种特殊的图结构。也就是说图可以简化成类似树形的结构(如果是连通图,可简化成一棵生成树;非连通图,可简化成若干生成树组成的生成森林。但是本质上图还是图。)
分类
- 有无方向:
- 无向图
- 有向图(对应顶点的关系可用入度+出度描述)
- 依据关系数目划分:
- 完全图(每个顶点都具有n-1条边,共n*(n-1)/2条边。若为有向图的话,即有去也有回,即n*(n-1)条弧)
- 稀疏图(边或弧相对较少)
- 稠密图(边或弧相对较多)
- 依据连通性划分:
-
连通图(对于无向图,任意两个顶点都存在路径)
-
强连通图(对于有向图,任意两个顶点都存在路径可以相互访问)
对于无向图来说,两顶点存在路径(边)即视为是连通的;而对于有向图来说,需要区分方向,两顶点间必须存在路径可相互访问才能算是连通的,此时称做强连通。
存储方式
-
顺序存储:
借助于数组,可使用二维数组,下标指示两个顶点,对应存储值表述边。使用二维数组的方式,能清晰地表述有向图的所有关系。但是存储无向图时,其实没必要用两个存储空间存储同一条边,毕竟无向图不区分方向。此时可以使用其中一边存储,但是这样并未节省空间,我们还是开辟了一个二维数组(矩阵)去存储这样一个无向图。其实可以将上三角矩阵或者下三角矩阵的信息压缩映射成一维数组存储,这样能节省一半的空间,同时具有随机访问的优点。 -
链式存储:
邻接表,类似于哈希表,主要是为了节省空间,当邻接矩阵存储时存在大量未使用空间,我们可以使用顶点表(数组)+边表(单链表)的形式表示。顶点表顺序存储,以便于可以随机访问任意顶点,遍历其边表即可访问对应的边信息。但是节省空间的同时,牺牲了随机访问的优点。由于这种基本的结构中仅有一个边域,若存储有向入时,访问入度非常麻烦,需要遍历整个顶点表+边表才能确定对应结点是否存在入度。存在这样的问题就衍生出了一些基于链式存储优化的结构。
针对有向图,于是有了十字链表,邻接表顶点表结点中增加了入度域,方便找寻入度+出度。但是这样的结构查询方便,删除等操作简直就是灾难。
针对无向图,为了避免无向图邻接表存储时,边存储两次对结点空间的浪费,同时也考虑到删除方便于是有了邻接多重表。