前言
如果图按照邻接矩阵方法存储的话,在存储稀疏图或者是邻接矩阵并不规律的图时会造成大量存储空间的浪费。而之前也提到过,图的存储结构并不只有邻接矩阵法一种,而临界表就是其中一种存储方法,它面对稀疏图时会比邻接矩阵法更有优势。
邻接表的定义与实现
邻接表就是对于每个顶点都建立一个单链表,用来存储顶点与顶点之间的联系。
在邻接表中,存在两种结点结构,分别是代表顶点的node_v和代表边的node_arc。假设要存储的图为G,在G中有任意顶点,都有一个对应的单链表,链表的第一个结点均为代表该顶点的node_v结构的结点,而该结点后续指向的结点均为node_arc结构的边结点。每个顶点对应的单链表叫做该顶点的边表,边表的每个结点代表该边表对应的顶点是否有以该结点为代表的顶点的边。
结点结构体node_v分为两个部分,分别是代表顶点信息的data和指向边结点的指针arc。
结点结构体node_arc分为两个部分,分别是代表该边(弧)指向的顶点的位置pos以及指向以链表顶点为起点的其他边的指针next。
如果图G中共有v个顶点,那么图的边表最终有v个,所有边表的第一个结点均为node_v结构,后续结点为node_arc结构。
邻接表的C++语言实现如下:
#define maxSize 50
typedef struct node_v {
string data;
node_arc *arc;
}node_v,list[maxSize];
struct node_arc {
int pos;
node_arc *next;
//int weight; //如果边有权值可以把注释取消
};
struct ALGraph {
list list_v;
int num_v,num_arc;
};
邻接表的性质
- 每个图对应的邻接矩阵是唯一的,但是对应的邻接表并不唯一;
- 采用链表的形式进行存储,对于空间的利用率较高。
邻接表的特点
优点
- 容易找到某顶点的所有邻边;
- 容易计算某顶点的出度;
- 存放稀疏图的空间占用率相较于邻接矩阵大大降低;
缺点
- 确定两个顶点间是否存在边的速度低于邻接矩阵;
- 图对应的邻接表可能不止一个;
- 在求顶点入度的时候效率极低;
- 其存储形式在无向图中略显冗余。
适用
适用于边较为稀疏的稀疏图,以及有向图的存储。
其他存储方式
十字链表法
针对于有向图进行存储的一种链式存储方法。相较于邻接表法,顶点结点删去了next指针,增加了以该顶点为弧头的第一个弧结点指针nin和以该结点为弧尾的第一个弧结点指针nout;边结点(弧结点)包括5个域,分别代表弧头、弧尾的编号、指向弧头相同的下一个弧结点指针、指向弧尾相同的下一个弧结点指针和数据域。
相较于邻接表,其求顶点入度的时间大大缩短。
邻接多重法
针对于无向图的一种链式存储方法,这里不再详述。