数据结构基础攻略——图(Graph)

来源:互联网 发布:影音先锋官方下载mac 编辑:程序博客网 时间:2024/05/29 19:07

图(Graph)

1.基本概念

1)图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,可表示为G(V,E)。

2)图的边或弧具有与它相关的数叫做权(Weight)。这种带权的图称为网(Network)

3)在无向图中,与顶点v相关联的边的数目称为顶点v的度(Degree)。在有向图中,以顶点v为头的弧的数目称为v的入度(InDegree);以v为尾的弧的数目称为v的出度(OutDegree);顶点v的度为其入度与出度之和。

4)第一个顶点到最后一个顶点相同的路径称为回路或环(Cycle)。

5)在无向图G中,如果从顶点v到顶点u有路径,则称v与u是连通的;如果对于图中任意两个顶点u、v都是连通的,则G是连通图(Connected Graph)

6)在有向图G中,如果对于每一对u、v,从u到v和从v到u都存在路径,则G是强连通图;有向图中的极大强连通子图称作有向图的强连通分量。

7)一个连通图的生成树是一个极小的连通子图,它含有图中全部的n个点,但只有足以构成一棵树的n-1条边。

2图的存储结构

1)邻接矩阵(Adjacency Matrix)

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

2)邻接表(Adjacency List)

它是由顶点表和边表组成。其中,顶点表用各个顶点的data和firstedge两个域表示,data是数据域,firstedge是指针域;边表结点由adjvex和next两个域组成,adjvex是邻接点域,next是下一个结点的指针。

3)十字链表(Orthogonal List)

它是针对有向图提出的优化存储结构,把邻接表与逆邻接表结合起来,也是由顶点表和边表组成。其中,顶点表结点由data、firstin和firstout三个域组成,data是数据域,firstin是入边表头指针,firstout是出边表头指针;边表结点由tailvex、headvex、headlink、taillink四个域组成,tailvex和headvex分别是弧起点、弧终点在顶点表的下标,headlink和taillink分别是指向起点、终点相同的下一条边。

4)邻接多重表

它是针对有无图提出的优化存储结构,仿照了十字链表的结构。其中,顶点表用各个顶点的data和firstedge两个域表示,data是数据域,firstedge是指针域;边表结点由ivex、jvex、ilink、jlink四个域组成,ivex和jvex分别是该边的两个顶点在顶点表中的下标;ilink和jlink分别是指向依附在顶点ivex、顶点jvex的下一条边。

5)边集数组

它由顶点数组和边数组构成的。顶点数组是存储顶点信息;边数组每个数据元素由一条边的起点下标(begin)、终点下标(end)和权(weight)组成。在求最小生成树的Kruskal算法会用到边集数组。

3图的遍历(Traversing Graph)

从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程称为图的遍历。

1)深度优先遍历(Depth First Search)

它从图中某个顶点v出发,访问此顶点,然后从v的未被访问的邻接点出发深度优先遍历图,直到图中所有和v有路径相通的顶点都被访问到。(它是一个递归的过程,类似于一棵树的前序遍历)

2)广度优先遍历(Breadth First Search)

它从图中的某个顶点v出发,并访问此顶点,然后从v出发,访问v的各个未曾访问的邻接点u1、u2、……、uk,再依次从u1、u2、……、uk出发访问各自未被访问的邻接点……直到全部顶点都被访问为止。(它需要队列来存取顶点,类似于一棵树的层序遍历)

4.最小生成树(MinimumCost Spanning Tree)

构造连通网的最小代价生成树称为最小生成树。

1)普利姆(Prim)算法

它是一种连续地一步步长成最小生成树的一种方法。在每一步,都要把一个结点当作根并往上加边,即把相关联的顶点加到增长中的树上了。算法的任一阶段,通过选择边(u,v),使得(u,v)的值是所有未加入生成树的边的值中的最小值,并把这个新找出的顶点v添加到这棵树上(设u已经在树上)。Prim算法基本上与求最短路径的Dijkstra算法相同的。算法的时间复杂度为O(n2)。

2)克鲁斯卡尔(Kruskal)算法

它是连续地根据边上权值的升序排列来选择边,当所选的边不产生回路时,就把该边添加到生成树集合中,否则放弃该边继续检验一条边是否满足不产生回路的条件,重复此操作,直到所有顶点都在同一个连通分量上(生成树被添加了n-1条边)。操作过程中,用到了边集数组来表示图。算法的时间复杂度为O(eloge)。

5最短路径(Shortest Path)

对于网图来说,最短路径是指两顶点之间经过的边上权值之和最小的路径。并且,我们称路径上的第一个顶点为源点,最后一个顶点为终点。

1)迪杰斯特拉(Dijkstra)算法

与最小生成树的普利姆(Prim)算法相似。在每个阶段,Dijkstra算法选择一个在源点和终点之间的顶点v,它在所有未被选中的顶点中具有最短路径,在这个最短路径的基础上再求其他更远顶点的最短路径,直到到达终点为止。算法的时间复杂度为O(n2)。

2)费洛伊德(Floyd)算法

在求顶点u到顶点v的最短路径,我们假设D(u,v)为u到u的最短路径的距离,如果我们能够找到一个中间结点w,使得D(u,w)+ D(w,v) < D(u,v)成立,则从u到w再到v的路径比u直接到v的路径短,所以可以用D(u,w)+ D(w,v) 取代 D(u,v),当遍历完所有的中间点w,D(u,v)就是u到v的最短路径的距离。算法中通过一个对应顶点的最小路径的前驱矩阵来存储路径。算法的时间复杂度为O(n3),因为它完成了所有顶点到所有顶点的最短路径的计算。

6拓扑排序(Topological Sort)

在一个有向图G中,将G中所有顶点排成一个线性序列,使得图G中边集E上的任意一条边(u,v),在顶点序列中顶点u必须在顶点v之前。

1)AOV网(Activity On Vertex Network)

在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,称为AOV网。

2)AOV网的拓扑排序

开始时将AOV网中所有入度为0的顶点入栈,再选择一个入度为0的顶点出栈,同时删除以此顶点为尾的弧(此顶点的邻接点的入度减少1),并将新增的入度为0的顶点压入栈,继续重复次步骤,直至输出全部顶点或者AOV网中不存在入度为0的顶点为止。

7关键路径(Critical Path)

1)AOE网(Activity On Edge Network)

在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网,我们称之为AOE网。

2)关键路径算法

先对AOE网进行拓扑排序,并且计算各个顶点的etv,再根据etv、ltv、ete和lte之间的关系计算出ltv、ete和lte,最后再判断哪些活动的ete与lte相等,则该活动即为关键活动。所求出的关键活动一起组成关键路径。

a)事件的最早发生时间etv(earliest time of vertex)

顶点k的最早发生时间计算如下:

etv(k)=max{etv(j)+weight<j,k>},j∈T

其中,T是以顶点k为尾的所有弧的头顶点的集合,对于顶点0(源点),即k=0,etv(0)=0。

b)时间的最晚发生时间ltv(latest time of vertex):即顶点v的最晚发生时间,超过此时间会延误整个工期。

从完成汇点 出发,即k=n-1,此时有ltv(k)=etv(k),按逆拓朴序列求各个顶点的ltv:

ltv(k)=min{ltv(j)-weight<k,j>},j∈S

其中, S 是以顶点j为头的所有弧的尾顶点集合。

c)活动的最早开工时间ete(earliest time of edge):

弧<j,k>的最早发生时间

ete(<j,k>)=etv(j).

d)活动的最晚发生开工时间lte(latest time of edge):不延误工期的最晚开工时间。

弧<j,k>的最晚开工时间

lte(<j,k>)=ltv(k) -weight<j,k>.

如果ete(<j,k>)与lte(<j,k>)相等,则活动<j,k>即为关键活动。

原文转载出处:http://50vip.com/blog.php?i=158