图论算法汇集

图的分类

方向:有向图()、无向图<>

边带不带权:带权图(网)、无权图

特殊的图:无向完全图(任意两个顶点都有边)、有向完全图(任意两个顶点都有方向相反的两条弧)
                 无向连通图(任意两顶点都是连通的)
                 有向连通图:强连通图(有向图任意两顶点,都存在相对的路径,如v1->v2和v2->v1);
                                      单向连通图(有向图任意节点v1、v2,至少存在从v1到v2和v2到v1路径中的一条)
                                      弱连通图(若将有向图的所有边替换为无向边后为无向连通图,则该有向图为弱连通图)

 

图的存储

邻接矩阵:

用两个数组来表示图。一个一维数组存储图的顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息。

邻接表:

一般用一个一维数组(或者一个链表)和多个链表构成。
一维数组(或一个链表):用来存储图中的顶点信息,另外每个顶点信息还存储着指向第一个邻接点的指针。
多个链表:分别存储着每个顶点的所有邻接点,无向图称为顶点的边表,有向图称为以顶点作为弧尾的出边表。
若是有向图的话只关心出度的话可以和无向图相同用下图的存储方法,若也关心入度的话,可以再建一个逆邻接表。

十字链表:

专门针对有向图的存储方法,把邻接表和逆邻接表结合起来。(在有向图中,是非常好的数据结构模型)
仍由一个一维数组(或链表)和多个链表组成,只是数组元素结构和链表元素结构有所变化:
数组元素(表示顶点)结构改变如下:

其中firstin指向第一条以该顶点为弧头的入边的弧的指针。
firstout指向第一条以该顶点为弧尾的出边的弧的指针。

链表元素(表示弧)结构改变如下:

tailvex:该弧的起点在顶点表(一维数组)中的下标
headvex:该弧的终点在顶点表(一维数组)中的下标
headlink:指向终点相同的下一条弧
taillink:指向起点相同的下一条边
注:如果是网(有权图),可以再增加一个weight域。


虚线即是逆邻接表的表示。

十字链表结构看起来复杂一点,但创建图的算法的时间复杂度和邻接表相同。

邻接多重表:

用来表示无向图,是对无向图的一种优化(个人感觉还不如邻接表好用),主要是邻接表中一条边存储了两次,删除的时候不太方便,如(v0-v1)在v0的链表中存储了一次,在v1的存储结构中又存储了一次。

邻接多重表依旧用一个顶点一维数组和多个边的链表来表示,只是对边的元素的结构做了一定的修改,如下:
边的结构调整如下:

ivex、jvex:该边依附的两个顶点在顶点一维数组中的下标。
ilink:指向依附顶点ivex的下一条边。
jlink:指向依附顶点jvex的下一条边。


左图中:4个顶点、5条边。我们先将4个顶点的一维数组和5条边的结构列出来,如右图。ivex和jvex的位置可以互换。
开始连线,首先将四个顶点的firstedge指向关联的一条边,紧接着将关联的边的指针填到对应ilink或jlink位置。
注:有5条边,所以有10条连线:

 

边集数组:

适用于有向图和无向图,主要适合对边依次进行处理的操作,不适合对顶点相关的操作。
边集数组由两个一维数组构成,一个存储顶点的信息,一个存储边的信息。
边的数组的每个数据元素存储一条边的起点、终点(对于无向图,可选定边的任一端点为起点或终点)和权(若有的话),各边在数组中的次序可任意安排,也可根据具体要求而定。


 

 

图的遍历:

深度优先遍历(DFS)

递归实现 类似树的前序遍历

广度优先遍历(BFS)

类似于树的层序遍历

图的算法

最小生成树

普里姆算法(Prim)

从一个顶点出发,找往外扩散的最小的边,扩散出去之后,再找从这两个点往外扩散的最小的边,一直进行下去,直到把所有顶点都访问到,也就是用n-1条边把n个顶点连接起来。

克鲁斯卡尔算法(Kruskal)

先构建边集数组,并且对它们按权值从小到大排序。然后假设该网只有n个顶点而无边。图的每个顶点都自成一个连通分量。然后从边集数组中找代价最小的边(已经排好序了),若该边的两个顶点落在两个不同的连通分量上,则将其加入到图中,否则将其舍弃选择下一条边。以此类推,直到图中所有的顶点都在同一个连通分量上。
判断是否在两个不同的连通分量上用:并查集。

 

最短路径

迪杰斯特拉算法(计算从指定起点到其他所有点的最短距离)

从指定源点的所有邻接点中找一个最近的邻接点(把这个点存到一个已经确定距离的集合中,该集合是不用再计算距离的)。判断从源点出发,经过最近的这个邻接点到达所有顶点的距离是否小于源点直接到达所有顶点的的距离,如果小于则替换一下源点到该顶点的最小距离的记录。此次循环完毕之后,再从没有确定距离的点中找一个距离最小的,并且添加到已经确定距离的集合中,并且再做上述操作。一直循环,直到所有的顶点都确定距离了。

弗洛伊德算法(计算从任意点到任意点的最短距离)

1先构建邻接矩阵。

2把邻接矩阵每两个点之间的距离都用绕过矩阵中任意一个或多个顶点来得到最小距离。

 

3循环判断任意两顶点之间的距离是否大于经过矩阵任意一点然后到达的距离。如果大于则将两点间的距离替换为经过该点之后的距离,此时就代表经过该点。循环完所有的顶点就代表已经判断了经过所有点的距离了。

例如:总共有10个顶点,要求从0到9的最短距离,循环了10次,计算了经过点1-8的距离,所以得到的是最短距离。

 

4问题:绕这些点的先后顺序对结果有没有影响?也就是循环是从经过点0开始,到经过最后一个点结束,和从经过最后一个点开始,到经过点0结束有没有区别?为什么?

个人思考的答案:

没有区别!

因为当循环到经过某一点时,是优化了所有经过该点的路径,即便有一些当下没有用到,但之后需要用到的时候,实际现在已经做了优化了。

例如:从0-->5的最优路径是0  2  1  5 。一开始循环的是1实际已经优化了2à5的路径,下次循环2的时候0à5实际就是0  2  1  5

 

有向无环图的应用

拓扑排序

AOV网(Activity On VertexNetwork):(有向、无环图):在一个表示工程的有向图中,顶点表示活动,弧表示活动间优先关系,这样的有向图为顶点表示活动的网,称为AOV网。AOV网中不能存在回路。

拓扑序列:设G=(V,E)是一个具有n个顶点的有向图,V是所有顶点的集合,若V中的顶点排列顺序满足:若从顶点vi到vj有一条路径,则在顶点序列V中vi必须在vj之前。则称V这样的顶点序列为一个拓扑序列。(拓扑序列只存在有向无环图中,拓扑序列是一个所有顶点的集合)
注:一个AOV网可以有多个拓扑序列

拓扑排序:对一个有向图构造拓扑序列的过程。构造时有两个结果,如果此网的全部顶点全被输出,则说明该网是不存在环的AOV网,若输出顶点数少了,则说明该网存在环,不是AOV网。(若理解不了,请结合上面拓扑序列定义和下面拓扑排序算法)

拓扑排序算法:从AOV网选择一个入度为0的顶点输出,然后删除此顶点,并删除以此顶点为尾的弧,重复此步骤,直到输出全部顶点或AOV网中不存在入度为0的顶点为止。

 

关键路径

AOE网(Activity On EdgeNetwork):(有向、无环、有权图):在表示工程的带权有向图中,顶点表示时间,弧表示活动,权值表示活动持续的时间,称为AOE网,AOE网也不能存在回路。

路径长度:将路径上各个活动所持续时间之和称为路径长度。

关键路径:从源点到汇点具有最大长度的路径叫关键路径。

关键活动:在关键路径上的活动叫关键活动。

关键路径算法原理:用AOV拓扑序列的方法+权值计算

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值