数据结构与算法十一:2.4 图的存储结构--邻接多重表

182 阅读4分钟

这是我参与8月更文挑战的第30天,活动详情查看:8月更文挑战

关注我,以下内容持续更新

数据结构与算法(一):时间复杂度和空间复杂度

数据结构与算法(二):桟

数据结构与算法(三):队列

数据结构与算法(四):单链表

数据结构与算法(五):双向链表

数据结构与算法(六):哈希表

数据结构与算法(七):树和二叉树

数据结构与算法(八):排序算法

数据结构与算法(九):经典算法面试题

数据结构与算法(十):递归

数据结构与算法(十一):图


前面的文章介绍了几种图的存储方式邻接矩阵邻接表十字链表,本篇接续介绍图的另外一种存储方式:邻接多重表

邻接多重表(针对无向图邻接链表的优化)

首先明确两点:

  • 邻接多重表仅适用于存储无向图或无向网。
  • 邻接多重表是针对无向图的邻接表的优化,可看作是邻接表十字链表的结合。

邻接表.image

a)无向图的邻接表结构

无向图的邻接表中可以看到,每一条边(vi,vj)在邻接表中有两个边结点:一个在顶点vi的边链表中,表示(vi,vj);一个在顶点vj的边链表中,表示(vj,vi)。如果需要给被处理的边加标记(如访问标志或删除标志等),则需要同时给表示某一条边的两个边结点加标记,而这两个结点又不在同一个边链表中,所以需要对两个顶点的边表进行遍历,效率较低。邻接多重表可以简化这种操作,邻接多重表是针对无向图的邻接表的优化,可看作是邻接表十字链表的结合。 邻接多重表与邻接表的区别在于:同一条边在邻接表中用一个结点表示。而在邻接多重表中用两个结点表示。此外,邻接多重表中增加了标志域用以标记该条边是否被搜索过,避免了同一条边的重复搜索。邻接多重表请看下图图示

邻接多重表.png

b)无向图的邻接多重表结构

邻接多重表由顶点表结点VertexNode和边表结点EdgeNode两种结点构成。

  • 顶点表结点VertexNode由data和firstedge构成。
    • data:数据域,存储有关顶点的数据信息。
    • firstedge:边表头指针,指向依附于该顶点的边表。
  • 边表结点EdgeNode由ivex、jvex、ilink、jlink、mark构成。
    • ivex、jvex: 与某条边依附的两个顶点在顶点表中的下标;
    • ilink:指针域,指向依附于顶点ivex的下一条边;
    • jlink:指针域,指向依附于顶点jvex的下一条边;
    • mark:标志域,用于标记此结点点是否被操作过,mark域为0表示未被操作;mark为1表示该节点已被操作。
    • weight:信息域,用于存储边的权值(非网图不需要)
//顶点结点
typedef struct VertexNode{
    int data;
    EdgeNode* firstedge;
};
//边表结点
typedef struct EdgeNode{
    int mark;
    int ivex;
    EdgeNode* ilink;
    int jvex;
    EdgeNode* jlink;
    int weight;
};

图的各种存储结构的对比

至此为止,图的4种存储结构已经讲完了,最后总结下各种存储结构的特点和适应场景

  • 邻接矩阵:可以存储无向图,也可存储有向图。构造一个具有n个顶点和e条边的无向图的时间复杂度O(n*n+e*n),邻接矩阵的初始化消耗了O(n*n)的时间。
  • 邻接表:链式存储结构。可以存储无向图和有向图,有向图可以建立“逆邻接表”。构造邻接表或者“逆邻接表”时间复杂度O(n+e),n个顶点+e条边。邻接表相对于邻接矩阵如果是边稀疏图的话比较节约空间。但是邻接表要确定vi和vj是否有边的时候没有邻接矩阵方便。
  • 十字链表:有向图的另一种链式存储。在十字链表中容易找到以顶点vi为起点的弧,也容易找到以顶点vi为终点的弧,因而容易求得顶点的出度和入度。
  • 邻接多重表:无向图的另一种链式存储。方便于边的搜索和边的删除。

关注我

如果觉得我写的不错,请点个赞 关注我 您的支持是我更文最大的动力!