前言
数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷。
也因如此,它作为博主大二上学期最重要的必修课出现了。由于大家对于上学期C++系列博文的支持,我打算将这门课的笔记也写作系列博文,既用于整理、消化,也用于同各位交流、展示数据结构的美。
此系列文章,将会分成两条主线,一条“数据结构基础”,一条“数据结构拓展”。“数据结构基础”主要以记录课上内容为主,“拓展”则是以课上内容为基础的更加高深的数据结构或相关应用知识。
欢迎关注博主,一起交流、学习、进步,往期的文章将会放在文末。
基于图的基础概念,要在计算机中存储一个图,需要保存这个图的点集和边集。
保存所有节点的信息是容易的,节点总是有编号或者可编号的,因此可以考虑使用链表或者线性表来存储和快速检索节点信息。
大多数情况下对图不涉及频繁的增删节点,而是频繁的检索各个节点的信息,所以还是推荐使用数组来存储接地那信息。
相较于节点,保存边集总不是那么容易,一方面边不能脱离节点单独存储,一条边连接两个节点,是两个节点间的一个关系;另一方面,边集的规模比较大,在没有重边的情况下,完全无向图边的数量为 C n 2 = n ( n + 1 ) 2 C^2_n=\frac{n(n+1)}{2} Cn2=2n(n+1)条边,这个规模是 n 2 n^2 n2级别,如果选择了不恰当的存储结构,冗余的空间将会是巨大的浪费。
那么这一节,我们将介绍两种存储图的方法:邻接矩阵和邻接表
邻接矩阵
邻接矩阵是使用一个 n ∗ n n*n n∗n的矩阵 A = ( a i j ) A=(a_{ij}) A=(aij)来表示一张图。用矩阵中的每一个元素就表示了一对点之间的边信息。
无权图的邻接矩阵
对于无权图,邻接矩阵有:
- a i j = 0 a_{ij}=0 aij=0,节点i和节点j之间不存在边
- a i j = 1 a_{ij}=1 aij=1,节点i和节点j之间有一条边由i指向j
对于下面的有向图:
其邻接矩阵为:
从该图中我们可以看到,由于不存在指向自己的边,所以矩阵的主对角元素都是0
对于如下无向图:
其邻接矩阵为:
可以发现,对于无向图,邻接矩阵总是对称的。如果节点i和节点j之间存在无向边,则 a i j = a j i = 1 a_{ij}=a_{ji}=1 aij=aji=1。这个也给了我们一个启示,即无向边可以看作两条方向相反的两条有向边。
代码实现
在程序中,完全可以使用二维数组来模拟矩阵,我们用矩阵a[i][j]来表示 a i