54-图的邻接表存储结构

  我们知道图的存储结构有邻接矩阵存储方法和邻接表存储方法,而对于邻接矩阵我们已经学习过了,本篇将主要介绍图的邻接表存储结构。

这里写图片描述
图1-图的邻接表存储结构

1. 邻接表存储有向图

这里写图片描述
图2-邻接表存储有向图

  邻接表存储方法是对图中每个顶点i建立一个单链表,将顶点i的所有邻接点链接起来,然后再给每个单链表上附设一个表头节点(表示顶点信息),将所有表头节点构成一个数组(顺序表),下标为i的元素表示顶点i的表头节点,因此不难看出单链表中的每个节点代表着一条边,我们称之为边节点

2. 邻接表的存储结构

  从邻接表存储方法我们可知,图的邻接表存储方法是一种顺序分配和链式分配相结合的存储方法。而且邻接表中有两类节点:表头节点和单链表中的边节点。

  如图2所示,在表头节点中的data域表示每个顶点的信息,firstarc域用于指向单链表的第一个边节点(即相关联的邻接点),而单链表中的每个边节点又包括了adjvex域,nextar域,info域。

  adjvex域用于存储某顶点的邻接点,而nextar域则用于指向单链表中的下一个边节点,而info域则用于存储边节点信息,如权值。



由以上这些信息,我们可以定义邻接表存储结构,如下所示:

typedef struct ANode
{
    int adjvex;                 //记录某顶点的邻接点
    struct ANode *nextarc;      //指向下一条边节点的指针
    InfoType info;              //记录边的权值等信息

} ArcNode;                  //边表节点类型


typedef struct Vnode
{
    Vertex data;            //存储顶点的信息
    ArcNode *firstarc;      //指向第一个边节点

} VNode;                //表头节点类型

typedef VNode AdjList[MAXV];

typedef struct
{
    AdjList adjlist;    //邻接表,这其实是一个数组(顺序表)
    int n,e;            //记录顶点个数n,边数e

} ALGraph; //完整的图邻接表类型

3. 邻接表存储无权图

这里写图片描述
图3-邻接表存储无权图

  我们可以看到邻接表存储无权图有一些区别,比如对于单链表的边节点的存储结构来说,由于是无权图,边节点的存储结构少了info域,那么定义如下所示:

typedef struct ANode
{
    int adjvex;                 //记录某顶点的邻接点
    struct ANode *nextarc;      //指向下一条边节点的指针

} ArcNode;                      //边表节点类型


4. 邻接表的特点

  1.邻接表表示不唯一,也就是说,在每个顶点对应的单链表中,各边节点的链接次序可以是任意的。

这里写图片描述

  比如顶点0对应的单链表中各边节点链接次序可以是顶点1,顶点3,顶点4,;也可以是顶点3,顶点1,顶点4。各个节点的链接次序可以是随意的。

  2. 邻接表适合存储稀疏图,边数越大,存储空间也越大,而稀疏图的边很少,存储起来则更加节省空间。

  3. 对于无向图,邻接表的顶点i对应的第i个链表的边节点数目正好是顶点i的度。

  4. 对于有向图,邻接表的顶点i对应的第i个链表的边节点数目仅仅是顶点i的出度;其入度为邻接表中所有adjvex域值为i的边节点数目,必须查找邻接表中的所有顶点,而这个过程是非常耗时的。



总结:
  我们在学习数据结构时,会学到非常多的,各种各样的数据结构,而对于这些不同的数据结构,我们要根据合适的应用场景,选择合适的数据结构,这是我们需要掌握的一种非常重要的能力。

猜你喜欢

转载自blog.csdn.net/qq_35733751/article/details/81088378
今日推荐