图
定义
- 图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V表示图G中顶点的集合,E表示图G中边的集合
图和线性表的区别
- 在线性表中,数据元素之间是被串起来的,仅有线性关系,每个数据元素只有一个直接前驱和直接后继
- 在图形结构中,结点之间的关系是可以任意的,图中任意两个数据元素都可能相关
各种概念
- 无(有)向边:两顶点之间的边没有(有)方向,有向边也称为弧,有弧头和弧尾。无向边用小括号表示,有向边用尖括号表示
- 无向完全图和有向完全图
- 稀疏图和稠密图
- 网:带权的图
- 子图
- 度:某顶点和其相关的边的数目。度=入度(以顶点为头) + 出度(以顶点为尾)
- 路径长度:路径上的边或弧的数目(针对无向图)
- 简单路径:路径序列中顶点不重复出现的路径
连通图
- 在无向图G中,如果从顶点v到顶点v’有路径,则称v和v’是连通的。如果对于图中任意两顶点,它们都是连通的,则称图G是连通图
- 连通分量:无向图中的极大连通子图
- 有向图:强连通图。
- 强连通分量:有向图中的极大强连通子图
- 生成树:所谓的一个连通图的生成树是一个极小连通子图,它含有图中全部的n个顶点,但只有足以构成一棵树的n-1条边
- 有向树:有向图中一顶点入度为0其余顶点入度为1
存储结构
邻接矩阵
- 使用两个数组来表示图:一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息
- 在网图中,数组元素的值为对应的权,0或者infinity
- 时间复杂度为O(n^2+n+e)
邻接表
- 考虑对边或弧使用链式存储的方式,避免顺序结构带来的空间浪费问题
- 邻接表:数组与链表相结的存储方法(以顶点为弧尾存储链表,对应出度)
- 图中的顶点用一个一维数组存储,每个顶点vi的所有邻接点构成一个线性表,由于邻接点个数不定,使用单链表存储
- 顶点表结点结构:data,firstedge(指针域,指向边表的第一个结点)
- 边表结点结构:adjvex(邻接点域,存储某顶点的邻接点在顶点表中的下标),next(存储指向边表中下一个结点的指针)
- 时间复杂度为O(n+e)
- 逆邻接表:以弧头存储链表,对应入度
十字链表
- 主要针对有向图,结合了邻接表+逆邻接表
- 可以同时了解到顶点的出度和入度
- 顶点表结点结构:data,firstin(入边表头指针,指向该顶点的入边表中第一个结点),firstout(出边表头指针,指向该顶点的出边表中的第一个结点)
- 边表结点结构:tailvex(弧起点在顶点表中的下标),headvex(弧终点在顶点表中的下标),headlink(入边表指针域,指向终点相同的下一条边),taillink(边表指针域,指向起点相同的下一条边)
邻接多重表
- 更关注边的操作,仿照了十字链表的方式
- 重新定义的边表结点结构:ivex,ilink,jvex,jlink,其中ivex和jvex是与某条边依附的两个顶点在顶点表中的下标。ilink指向依附顶点ivex的下一条边,jlink指向依附顶点jvex的下一条边
边集数组
- 由两个一维数组组成:一个是存储顶点的信息;另一个是存储边的信息,这个边数组每个数据元素由一条边的起点下标、终点下标和权组成
- 更适合对边依次进行处理的操作,不适于对顶点进行操作
图的遍历
- 图的遍历:从图的某一顶点出发,访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程称为图的遍历
深度优先遍历
- 从图中某个顶点v出发,访问此顶点,然后从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到。若图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
- 与树的前序遍历类似
广度优先遍历
- 类似于树的层序遍历
- 深度优先更适合于目标比较明确,以找到目标为主要目的的情况;而广度优先更适合在不断扩大遍历范围时找到相对最优解的情况。