用树结构存储的图博客(笑)

导言

《英雄传说6:空之轨迹》是由日本 Falcom 公司开发制作并发行一款角色扮演类游戏。轨迹系列的舞台是“塞姆利亚大陆”,游戏故事发生在利贝尔王国,主人公艾丝蒂尔和约修亚将在冒险旅途上遇到各色各样的人物,以成为正式游击士为目标,揭开了故事的序幕,两位游击士新人为了磨练自我而踏上旅程,却在不经意间卷入震撼全王国乃至全大陆的重大事件之中。

当然我不是来给你推荐游戏的嘞,而是我想请你看一下角色关系图:

我们会发现啊,其实在实际的生活之中,往往描述事物之间的关系时,遇到的不是一对一或一对多的关系,而是多对多的关系。就例如任务关系,你看上图,约修亚与其他角色的关系就显得较为复杂一些,这是因为我们在与其他人产生联系时,别人也与我们产生了联系,这种联系是相互的。第一张利贝尔王国的地图也是如此,各个地区之间的地理位置如何?可以用什么方式到达另一个地区?当我们需要描述这样的多对多的关系时,发现线性结构和树结构都不太好用了,因此我们就提出了图结构来描述。

什么是图?

图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G (V , E),其中 G 表示一个图,V 是图 G 中的顶点集合,E 是图 G 中边的集合。那么什么是顶点呢?对于图中的数据元素我们就称之为顶点,就和我们成线性表的数据元素为元素,树的数据元素是结点是一个道理的,是一种说法而已。在线性表中,数据元素之间存在线性关系,在树结构中数据元素之间有层次关系,但是对于图中的任意两个顶点,它们之间都可能产生联系,边就是对顶点之间的关系的描述。

有向图与无向图

图按照有无方向分为无向图和有向图。无向图由顶点和边构成,有向图由顶点和弧构成,弧有弧尾和弧头之分。这么讲不好理解,我们说人话,简单地说无向图就是一旦两个顶点之间有联系,那么这种联系就是双向的,而有向图就是说两个顶点之间的关系可能是单向的,例如下面两张图,左图是一个无向图,例如对于顶点 A 和顶点 C,由于不考虑方向,两个顶点之间关系就是双向的,而对于右边的有向图而言,对于顶点 A 和顶点 C 中只有 C—>A 有产生联系,是一种单向的联系。

同时对边的多少可以有感性的刻画,边较少的图结构称之为稀疏图,边较多的结构称之为稠密图

在实际应用中,边具有的信息量往往不唯一,例如用图描述地图的话,边就可以负载距离等信息。对于边负载的具有特殊含义的数据,我们称之为,为这种权提供负载的图结构称之为

图的存储结构

出度、入度

顶点 v 的为和 v 相关联的边的数量,入度是以顶点 v 为头的弧的数量,出度是以顶点 v 为尾的弧的数量。

邻接点

对于无向图来说,若边 (v1,v2) 存在,那我就称 v1 和 v2 互为邻接点,或者 v1 和 v2 相互邻接。

存储结构

图中的一个顶点会和多个顶点产生联系,这就导致了图结构不能够被简单的存储结构直接存。如果把和一个顶点有关联的顶点都链到这个定点上,操作只会变得复杂且难以提取,这么做意义不大。所以我们就需要一些特殊的结构,来对顶点和顶点间的关系进行描述。
左转博客图的存储

图的遍历

对于图结构来说,图的遍历和树的遍历有类似之处,树结构的遍历从根结点出发,图结构的遍历从某一结点出发。出发之后,按照某种手法无重复地访问所有的结点,这也是后续解决图的连通性、拓扑排序和关键路径的预备知识。
由于在图结构中,任意顶点都有可能与其他顶点相互邻接,因此如果没有对已走过的路径进行记录的话,很有可能会由于结点的重复访问而无法遍历所有顶点。因此我们需要一种手法记录访问过的顶点,一种直接而有效的手法是使用一个 visited[n] 数组,先将其每一个元素初始化为 0,当我访问了第 i 个顶点时,就将 visited[i] 的值赋值为 1,表示已经访问过。当我访问某一个顶点时,可以通过 visited 数组来确定我接下来是否要从这个顶点往下走。
左转博客图的遍历

应用一:最小生成树

连通与连通分量

在无向图中,若从顶点 v1 到达顶点 v2 存在着边,那我就称 v1 和 v2 是连通的。对于一个图结构来说,任意 2 个顶点都是连通的,那我就称这个图结构为连通图。假设 2 个图结构存在着包含关系,被包含的图称之为子图连通分量这得是在无向图中的极大连通子图
对于有向图而言,若从 v1 到 v2 和从 v2 到 v1 都存在路径,则我们称该图结构为强连通图,有向图中的极大连通子图我们称之为强连通分量

生成树

首先我们拥有一个连通图,对于一个极小的连通子图,对于 n 个顶点而言仅存在 n - 1 条边来组织,我们就称该连通子图为连通图的生成树

最小生成树

在一个连通图中的所有生成树中,存在各边代价之和最小的生成树,则称该生成树为该联通网的最小代价生成树。例如通信网络的建设,可以用联通网表示,在一个图结构中的顶点可以用于表示 n 个城市,边表示顶点之间的路径,用权表示城市之间的距离,这个使我们判断成本的重要参考。
左转博客最小生成树

应用二:最短路径

路径长度

在无向图中,顶点 v1 到 顶点 v2 的路径往往需要跨越多个顶点进行转移,因此路径是一个顶点序列,若图结构是有向图的话,这个路径也会是有向的。对于路径经过的边或弧的数目,或弧上的权值的和被称之为路径长度

最短路径

我们在玩游戏中经常会使用自动寻路功能啦,例如魔兽争霸、环世界等游戏地图就复杂多了,因此路径的选择肯定是有算法的支撑。我们来考虑一个较为简易的情景,假设我这张地图使用顶点和路径描述,那我要从某个顶点到达另一个顶点,肯定是愿意选择最短的路径了,此时要去考虑什么样的路径,边的权值相加最小?
左转博客最短路径

应用三:拓扑排序

回路\环

若有一个路径满足其第一个顶点和最后一个顶点相同,则我称这条路径为回路。对于路径中顶点不重复出现的路径,我称之为简单路径,对应的回路就称之为简单回路

拓扑排序

小学有一种奥数题型叫“最优化策略”,诞生出这种题型的原因是由于完成一系列操作是由有先后顺序的,同时做一些事情的同时可以顺手做另一件事情。若这些事情是以一个无序线性地去完成,很明显是不现实的,因为有的事件是其他事件的预备条件,就例如要放茶叶的话就要有茶叶,买茶叶就是放茶叶的预备条件。而有些是可以并行地去做,例如烧开水和洗茶杯这两件事情可以交换顺序做,亦可以一起做。
左转博客拓扑排序

参考资料

《大话数据结构》—— 程杰 著,清华大学出版社
《数据结构(C语言版|第二版)》—— 严蔚敏 李冬梅 吴伟民 编著,人民邮电出版社
图的存储
图的遍历
最小生成树
最短路径
拓扑排序

posted @ 2020-05-04 03:02  乌漆WhiteMoon  阅读(364)  评论(0编辑  收藏  举报