为实习准备的数据结构(11)-- 图论算法 集锦(1)

这许许多多地铁站所组成的交通网络,也可以认为是数据结构当中的图。

图,是一种比树更为复杂的数据结构。树的节点之间是一对多的关系,并且存在父与子的层级划分;而图的顶点(注意,这里不叫节点)之间是多对多的关系,并且所有顶点都是平等的,无所谓谁是父谁是子。


图的相关定义


定义一:有向图、无向图、权重、活用图

图是由顶点的有穷非空集合和顶点之间边的集合组成, 通常表示为: G(V,E), 其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。

在这里插入图片描述

这种叫做无向图,里面的边叫做无向边。

图有各种形状和大小。边可以有权重(weight),即每一条边会被分配一个正数或者负数值。考虑一个代表航线的图。各个城市就是顶点,航线就是边。那么边的权重可以是飞行时间,或者机票价格。

在这里插入图片描述

边可以是有方向的。在上面提到的例子中,边是没有方向的。有方向的边意味着是单方面的关系。

在这里插入图片描述

事实证明图是一种有用的数据结构。

如果你有一个编程问题可以通过顶点和边表示出来,那么你就可以将你的问题用图画出来,然后使用著名的图算法(比如广度优先搜索 或者 深度优先搜索)来找到解决方案。

离散数学中有不少这方面的栗子。

假设你有一系列任务需要完成,但是有的任务必须等待其他任务完成后才可以开始。你可以通过非循环有向图来建立模型:

在这里插入图片描述

每一个顶点代表一个任务。两个任务之间的边表示目的任务必须等到源任务完成后才可以开始。比如,在任务B和任务D都完成之前,任务C不可以开始。在任务A完成之前,任务A和D都不能开始。

现在这个问题就通过图描述清楚了,你可以使用深度优先搜索算法来执行执行拓扑排序。这样就可以将所有的任务排入最优的执行顺序,保证等待任务完成的时间最小化。(这里可能的顺序之一是:A, B, D, E, C, F, G, H, I, J, K)


定义二:完全图、连通图、连通分量、生成树

在图中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。目前讨论的都是简单图。在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。含有n个顶点的无向完全图有n*(n-1)/2条边。在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向完全图。含有n个顶点的有向完全图有n* (n-1) 条边。

在无向图G中,如果从顶点v到顶点v’有路径,则称v和v’是连通的。 如果对于图中任意两个顶点vi、vj ∈E, vi,和vj都是连通的,则称G是连通图。

无向图中的极大连通子图称为连通分量。注意连通分量的概念,它强调:

要是子图;

子图要是连通的;

连通子图含有极大顶点数;

具有极大顶点数的连通子图包含依附于这些顶点的所有边。

所谓的一个连通图的生成树是一个极小的连通子图, 它含有图中全部的n 个顶点,但只有足以构成一棵树的n-1条边。比如下图的图1是一普通图,但显然它不是生成树,当去掉两条构成环的边后,比如图2 或图3,就满足n个顶点n-1条边且连通的定义了, 它们都是一棵生成树。从这里也可知道,如果一个图有n 个顶点和小子n-1条边,则是非连通图,如果多于n-1 边条,必定构成一个环, 因为这条边使得它依附的那两个顶点之间有了第二条路径。比如图2 和图3,随便加哪两顶点的边都将构成环。 不过有n-1条边并不一定是生成树,比如图4。

在这里插入图片描述

定义三:邻接表、邻接矩阵

理论上,图就是一堆顶点和边对象而已,但是怎么在代码中来描述呢?

有两种主要的方法:邻接列表和邻接矩阵。

在邻接列表实现中,每一个顶点会存储一个从它这里开始的边的列表。比如,如果顶点A 有一条边到B、C和D,那么A的列表中会有3条边

在这里插入图片描述

在邻接矩阵实现中,由行和列都表示顶点,由两个顶点所决定的矩阵对应元素表示这里两个顶点是否相连、如果相连这个值表示的是相连边的权重。例如,如果从顶点A到顶点B有一条权重为 5.6 的边,那么矩阵中第A行第B列的位置的元素值应该是5.6:

在这里插入图片描述

邻接列表只描述了指向外部的边。A 有一条边到B,但是B没有边到A,所以 A没有出现在B的邻接列表中。查找两个顶点之间的边或者权重会比较费时。

所以使用哪一个呢?大多数时候,选择邻接列表是正确的。下面是两种实现方法更详细的比较:

在这里插入图片描述


定义四:DFS、BFS

(1) 深度优先遍历(DFS)

a. 访问顶点v

b. 依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问

c. 若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止

在这里插入图片描述

(2) 广度优先遍历(BFS)

a. 从图中某个顶点v出发,访问v

b. 依次访问v的各个未被访问过的邻接点

c. 分别从这些邻接点出发依次访问他们的邻接点

d. 重复步骤c,直至所有已被访问的顶点的邻接点都被访问到

在这里插入图片描述


定义五:Prim 算法、Kruskal 算法、Dijkstra 算法

Prim 算法

a. 以某一个点开始,寻找当前该点可以访问的所有的边

b. 在已经寻找的边中发现最小边,这个边必须有一个点还没有访问过,将还没有访问的点加入集合,记录添加的边

c. 寻找当前集合可以访问的所有边,重复 b 的过程,直到没有新的点可以加入

Kruskal 算法

a. 设一个有n个顶点的连通网络为 G(V,E),最初先构造一个只有 n 个顶点,没有边的非连通图 T,图中每个顶点自成一个连通分量

b. 当在E中选择一条具有最小权值的边时,若该边的两个顶点落在不同的连通分量上,则将此边加入到 T 中;否则重新选择一条权值最小的边

c. 如此重复下去,直到所有顶点在同一个连通分量上为止

Dijkstra 算法

a. 遍历与结点1相连的所有结点,找到距离最近的一个&#x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值