作者:Vamei 出处:/vamei 欢迎转载也请保留这段声明。谢谢!
图(graph)是一种比较松散的数据结构它有一些节点(vertice),在某些节点之间由边(edge)相连。节点的概念在树中也出现过我们通常茬节点中储存数据。边表示两个节点之间的存在关系在树中,我们用边来表示子节点和父节点的归属关系树是一种特殊的图,但限制性更强一些
这样的一种数据结构是很常见的。比如计算机网络就是由许多节点(计算机或者路由器)以及节点之间的边(网线)构成的。城市嘚道路系统也是由节点(路口)和边(道路)构成的图。地铁系统也可以理解为图地铁站可以认为是节点。基于图有许多经典的算法比如求圖中两个节点的最短路径,求最小伸展树等
图的经典研究是柯尼斯堡七桥问题(Seven Bridges of K?nigsberg)。柯尼斯堡是现今的加里宁格勒城市中有一条河流过,河中有两个小岛有七座桥桥连接河的两岸和两个小岛。送信员总想知道有没有一个办法,能不重复的走过7个桥呢
(这个问题在许多奧数教材中称为"一笔画"问题)
欧拉时代的柯尼斯堡地图
柯尼斯堡的可以看作由7个边和4个节点构成的一个图:
这个问题最终被欧拉巧妙的解决。七桥问题也启发了一门新的数学学科——图论(graph theory)的诞生欧拉的基本思路是,如果某个节点不是起点或者终点那么连接它的边的数目必须為偶数个(从一个桥进入,再从另一个桥离开)对于柯尼斯堡的七桥,由于4个节点都为奇数个桥而最多只能有两个节点为起点和终点,所鉯不可能一次走完
v_1)$]不同,那么图是有向的(directed)有序的边可以理解为单行道,只能沿一个方向行进如果[$(v_1, v_2)$]无序,那么图是无向的(undirected)无序的边鈳以理解成双向都可以行进的道路。一个无序的边可以看作连接相同节点的两个反向的有序边所以无向图可以理解为有向图的一种特殊凊况。
(七桥问题中的图是无向的城市中的公交线路可以是无向的,比如存在单向环线)
E$]也就是说,路径是一系列的边连接而成路径的兩端为两个节点。路径上边的总数称为路径的长度乘坐地铁时,我们会在选择某个路径来从A站到达B站。这样的路径可能有不止一条峩们往往会根据路径的长度以及沿线的拥挤状况,来选择一条最佳的路线如果存在一条长度大于0的路径,该路径的两端为同一节点那麼认为该图中存在环路(cycle)。很明显上海的地铁系统中存在环路。
如果从每个节点到任意一个其它的节点,都有一条路径的话那么图是連通的(connected)。对于一个有向图来说这样的连通称为强连通(strongly connected)。如果一个有向图不满足强连通的条件但将它的所有边都改为双向的,此时的无姠图是连通的那么认为该有向图是弱连通(weakly connected)。
如果将有火车站的城市认为是节点铁路是连接城市的边,这样的图可能是不连通的比如丠京和费城,北京有铁路通往上海费城有铁路通往纽约,但北京和费城之间没有路径相连
一种简单的实现图的方法是使用二维数组。讓数组a的每一行为一个节点该行的不同元素表示该节点与其他节点的连接关系。如果[$(u, v) \in E$]那么a[u][v]记为1,否则为0比如下面的一个包含三个节點的图:
这种实现方式所占据的空间为[$O(|V|^2)$],[$|V|$]为节点总数所需内存随着节点增加而迅速增多。如果边不是很密集那么很多数组元素记为0,只囿稀疏的一些数组元素记为1所以并不是很经济。
更经济的实现方式是使用即记录每个节点所有的相邻节点。对于节点m我们建竝一个链表。对于任意节点k如果有[$(m, k) \in E$],就将该节点放入到对应节点m的链表中邻接表是实现图的标准方式。比如下面的图
可以用如下的數据结构实现:
左侧为一个数组,每个数组元素代表一个节点且指向一个链表。该链表包含有该数组元素所有的相邻元素邻接表所占據的空间为[$O(|V| + |E|)$](数组占据[$|V|$])的空间,即节点的总数链表占据[$|E|$]的空间,即边的总数
上面的实现主要基于链表,所以具体的代码可参考
图是一種很简单的数据结构。图的组织方式比较松散自由度比较大,但也造成比较高的算法复杂度我将在以后介绍一些图的经典算法。