现在的位置: 首页 > 综合 > 正文

图论相关知识和算法

2013年08月28日 ⁄ 综合 ⁄ 共 1676字 ⁄ 字号 评论关闭

1、无向图:简单路径(不存在节点到自身的loop)

有向图:回路(cycle),没有回路的有向图称为acyclic,有时简称为DAG。

无向图:如果任意两个节点之间存在一条路径,就成为连通。

有向图:上述性质称为强连通。不能满足上述性质,但有向图对应的底图(去掉方向后的有向图)满足上述性质,称为弱连通。

 

2、图的三种表示方法

(1)邻接矩阵:主要适合于dense图

(2)邻接表:主要适合于sparse图,具体实现方式也有多种,可以使用vector或list,也可以使用映射(节点为关键字,对应值为adjacency list)。如果使用vector最好对它的容器大小事先做好限制,不要使用默认的大小,否则空间效率就不高了。

(3)边表示:在有些应用条件下是很方便的。

 

3、关于图的一些常用算法

 

(1)图的拓扑排序(要求:有向图,无环)

算法思路:根据节点的入度来判断拓扑顺序。 数据结构使用:队列

 

(2)单源最短路径算法

 

这里主要考虑4种情况:

无权重的最短路径问题、有权重的最短路径问题、存在negative weight的有权最短路径问题、不存在回路的有权最短路径问题。

 

在最短路径问题中对于每个节点,预先设定三个信息变量:

Dv:表示距离开始节点的距离  Pv:本节点的父节点(用于还原路径)  Known:当节点是否已经处理完毕的标志

 

无权重的最短路径算法:

思路:图的广度优先搜索,使用的基本数据结构:queue。

 

 

Dijkstra's Algorithm(有权重的最短路径问题): 图中可以存在回路,但不能存在负权值的边或回路

思路:贪心算法

算法按阶段进行:每一个阶段,都从所有unknown节点中选择Dv最小的节点v,然后就将从s到v的最短路径设置为known。剩下的工作就是更新距离值Dw,这里Dw=Dv+Cv,w,这里的节点w是和节点v相邻的且为unknown的节点。

这里使用的数据结构:优先队列(由于算法中需要实时更新路径的距离,而priority_queue并不支持find操作,所以可以使用更高级的优先级队列来实现,如:pairing heap,或 Fabonacci Heap)。

 

当然,如果使用普通的优先队列也可以实现算法要求:只要某节点的距离值有更新,就将它插入到优先级队列中,只是在出堆的时候,如果该节点的最短距离版本已经出堆,那么后面该节点的其他版本就直接忽略掉,这样做的缺点只在于程序执行效率可能会较低,但算法实现比较容易。

 

不存在回路的有权最短路径问题:

思路:只要根据拓扑排序的顺序来一次选择节点,将它声明为known就可以了,可以和toplogical运算一起做,而且这样就不需要优先级队列了。

 

存在negative weight的有权最短路径问题:

思路:Dijkstra算法不适用了。但是可以将有权算法和无权算法结合在一起。

数据结构使用:queue。

 

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

最小生成树问题:

 

一个图存在最小生成树的前提:图是连通的。(所以执行最小生成树算法之前,一般需要进行连通性检测,如果是非连通的,那么就不存在对应的最小生成树)

最小生成树是acyclic,它本身是不唯一的,它所谓的“最小”就是它生成的树的所有边的代价是最小的。

下面介绍的两个算法都是基于贪心的思想(下面的算法都是基于无向图的,因为有向图比较复杂)

 

1、Prime Algorithm

这个算法的思想步骤非常类似于Dijstra‘s最短路径算法。

只是Dijstra算法中更新原则:dw=min( dv+cvw, dw);

而Prime算法使用的更新算法原则:dw=min( dw,cvw);

 

2、Kruskal Algorithnm

这个算法的主要思想是:每次都选择最短的边,然后判断这条边的两个节点是否已经在同一个集合中了,如果在就忽略掉这条边,如果不在同一个集合,就接受这条边。算法中止的条件是成功添加完|V|-1条边,因为图的|V|个节点只需要|V|-1条边就可以联通了

所以底层的数据结构使用的是并查集。

 

抱歉!评论已关闭.