基本概念

1.    图的定义:图G由顶点集V和边集E构成。点的个数也称为阶。注,图不能为空!点数不能为零,但是边数可以为零。

2.    有向图:有向边,<v, w> v为弧尾,w为弧头。

3.    无向图:图中的边无方向,<v, w>和<w, v>指的是一条边

4.    简单图:图中没有重复的边,也不存在顶点到自身的边

5.    多重图:和简单图的定义是相对的,也就是图中的两个结点之间的边数多于一条,也允许顶点通过一条边和自己关联

6.    完全图:任意两个顶点之间都存在边。无向完全图:n个顶点,有n(n-1)/2条边;有向完全图,任意两个顶点之间有方向相反的两条边。N个顶点,有n(n-1)条边。

7.    子图:两个图G=(V, E)和G’=(V’, E’),如果V’是V的子集,E‘是E的子集,那么G‘是G的子图,如果V = V’,那么G’为G的生成子图。注,V和E的子集并一定会构成一个子图,因为有可能组成的不是一个图。

8.    连通、连通图和连通分量:如果顶点v和顶点w之间有路径存在,说明v和w是连通的,如果图中任意两点之间都是连通的,那么称图G为连通图。无向图中的极大连通子图称为连通分量。对于无向图而言,n个顶点,如果边数小于n-1,那么一定是非连通图。注:极大连通子图为无向图的连通分量,极大要求该连通子图包括其所有的边。极小则既要求无向图的连通性,又要求图中的边数最少

9.    强连通图、强连通分量:有向图中,从顶点v到顶点w和从顶点w到顶点v之间都有路径,则称这两个结点之间是强连通的。如果有向图中,任意两个结点都是强连通的,那么称该图为强连通图。有向图中的极大连通子图为有向图的强连通分量。注:连通性一般指的是无向图、强连通性指的是有向图。

10.  生成树、生成森林:生成树是包含图中所有结点的一个极小连通子图。如果点数为n,则边数一定是n-1。对于生成树而言,砍去一条边就是非连通图,增加一条边,就会形成一个回路。在非联通图中,联通分量的生成树构成了非联通图的生成森林

11.  顶点的度、入度和出度:度为以该顶点为一个端点的边的个数。入度则是以顶点v为终点的有向边,出度则是以顶点v为起点的有向边。在无向图中,度数之和为边数之和的2倍;在有向图中,入度之和=出度之和=边数。

12.  边的权和网:边上赋予一定含义的数值,该数值称为权。带有权重的图也称为网。

13.  路径、路径长度和回路:顶点v到顶点w之间所有边的个数为路径长度,第一个顶点和最后一个顶点相同的路径称为回路或者环。在一个无向图中,如果边数大于n-1,则一定存在回路。

14.  简单路径、简单回路:路径中不存在重复顶点的为简单路径;除第一个和最后一个顶点之外,其余顶点不重复出现的回路为简单回路。

15.  距离:从顶点v出发到顶点w的最短路径若存在,则此路径称为v到w的距离,如果两点不连通,记该距离为无穷大

16.  有向树:有一个顶点入度为0,其余顶点的入度均为1的有向图称为有向树。

邻接矩阵法(顺序存储)

用一个一维矩阵表示图的结点,用一个二维矩阵表示图中边的信息。对于无权图,两个结点之间有边,则用1 表示;没有就用0表示。对于有权图,有边就用权值替代,没有边就用无穷大表示。

l  对于无向图,邻接矩阵为对称矩阵。

l  对于无向图,第i行的1之和表示该结点的度,因为是对称矩阵,第i列的1之和也是。

l  对于有向图,第i行的1之和表示该结点的出度,第i列的1之和为该结点的入度。

l  邻接矩阵很容易知道两个结点之间是否存在边。

邻接表法(链表法)

有顶点表和边表。对图中每个顶点都建立一个单链表,链表中存放该顶点的所有边。因此对于无向图而言,空间为n+2e;对于有向图,空间为n+e。

顶点结构:

顶点信息

边表头指针

边结构:

邻接点域

指针域

对于邻接表法,有向图的顶点的边表结点都是以该结点为尾结点的边。

图的邻接表法不是唯一的,但是由一个邻接表可以得到唯一的图。

邻接表很容易知道一个顶点的所有边,在邻接矩阵中则需要遍历某一行才可得,所用时间为O(n),但是在邻接表中寻找两个结点之间是否存在边,则比较费劲。另外对于有向图而言,寻找一个顶点的所有出边很简单,但是寻找一个结点的所有入边,就得遍历所有的边表。

十字链表(有向图的另一种链表法)

对应弧和顶点各有一种数据结构相对应。

弧结构:

尾结点

头结点

相同头结点的下一条弧

相同尾结点的下一条弧

顶点结构:

顶点相关信息

以该顶点为头的第一条弧

以该顶点为尾的第一条弧

十字链表中,弧头相同的弧在一条链表上;弧尾相同的弧在一条链表上

容易得到一个顶点的出度和入度。

十字链表并不是唯一的,但是一个十字链表可以得到唯一的图。

邻接多重表(无向图的另一种链表法)

因为在邻接表中不方便查找两个顶点之间是否存在边,用临接多重表就方便多了

边结构:

边相连的一个顶点A

依附于A点的另一条边

边相连的另一个顶点B

依附于B点的另一条边

点结构:

顶点的信息

依附于该顶点的第一条边

邻接多重表中,同一个顶点的边串联在一个链条上,以为每条边依附于两个顶点,所以每个边结点同时链接在两个链表中。

容易找到每个顶点的边数,以及两个顶点之间是否存在边。

广度优先搜索【BFS Breadth-First-Search】

BFS遍历相当于树的层次遍历,不是递归的算法,因此需要一个队列进行辅助。相似的思想还被用于Dijkstra单元最短路径和Prim最小生成树算法。

l  当采用邻接表作为存储方式时,每个顶点访问一次,每条边至少访问依次一次。因此时间复杂度为O(n+e)。当采用邻接矩阵作为存储方式时,每个点访问一次,查找每个点的邻接点也要O(n),所以时间复杂度为O()

l  广度优先生成树:因为给定图的邻接矩阵存储方式唯一,所以其广度优先生成树也是唯一的;因为图的邻接表存储方式不唯一,所以其广度优先生成树不是唯一的。

l  对于无向图的广度优先生成树,起点到所有顶点的路径都是最短路径,也是所有生成树中高度最小的。

l  使用BFS可以求非带权图的单源最短路径

深度优先搜索【Depth-First-Search、DFS】

l  DFS类似于树的先序遍历。是递归的算法,但是要借助一个递归栈来进行,因为有依次退回。

l        当采用邻接矩阵村存储时,因为主要是找邻接点,找每个顶点邻接点需要O(n),所以时间复杂度为O()。对于邻接表而言,找每个顶点的邻接点所用时间为O(e),所以时间复杂度为O(n+e)。

l  对于同样一个图,因为邻接矩阵的表达是唯一的,所以DFS和BFS遍历的序列是唯一的;但是邻接表的表示不唯一,所以基于邻接表得到的DFS和BFS的序列是不唯一的。

l  深度优先生成树和生成森林

l  对于连通图而言,调用DFS会产生深度优先生成树,否则就是深度优先生成森林。

l  用图的遍历可以判断图是否是连通的。对于无向图而言,连通分量数就是主函数中调用DFS或BFS的次数,但是对于有向图是不同的,因为有向图分强连通和非强连通。对于非强连通分量,调用一次DFS或BFS是没办法访问到该非强连通分量的所有顶点的。

利用深度优先遍历可以判断图是否存在回路

最小生成树

l  生成树是图的极小连通子图。包含图中所有顶点,并且只含有尽可能少的边。所以对于生成树,如果砍掉一条边,则会变成非联通的;若增加一条边,则会在图中形成回路。

l  对于一个带权连通无向图,生成树不同,每棵树上的权重之和也可能不同。其中边的权值之和最小的生成树为最小生成树。

l  最小生成树不是唯一的,它的树形可能不同。对于权值均不相同的的图来说,其最小生成树是唯一的。

l  最小生成树的权值之和一定是相同的,这是它的定义所形成的性质。

l  最小生成树的算法主要有Prim算法和Kruskal算法,两者都是基于贪心算法的策略。

Prim算法(最小生成树,O()

l        着重于点的一个算法,不依赖于边。时间复杂度为O()适合边稠密的图

l  顶点集V中先加入一个顶点,边集E初始化为空。然后从V中存在的顶点到不存在的顶点之间,寻找权值最小的一条边,加入E中。重复该过程,直到V中包含图G中的所有顶点。

Kruskal算法(最小生成树,O()

l      着重于边的一个算法,时间复杂度为:O() 在该算法中,用堆存放边的集合。

l  初始化顶点集V为空,边集E也是空。从图的边集和树的边集的差集中寻找一条权值最小的边,加入E中,然后将该边依附的两个顶点也加入V中。重复以上过程,直到V包含图中所有顶点。

最短路径

对于无权图,可以用广度优先搜索来实现。但是对于带权图则没办法用该方法实现

l  带权路径长度:从一个顶点A到其余任意顶点B的一条路径上所经过边上的权值之和定义为该路径的带权路径长度

l  最短路径:带权路径长度最短的那条路径,最短路径是允许有环的

l  单源最短路径:Dijkstra算法

l  每对顶点间的最短路径:Floyd算法

Dijkstra算法(单源最短路径,O()

l        时间复杂度为O(),如果想得到任意顶点之间的最短路径,时间复杂度为O()

l  算法基于贪心策略,对于权值为负数的图是不适用的,可以求解有回路的带权图

l  算法思想:用一个集合S来表示已求得的最短路径的顶点,用一个数组D表示所求点到该顶点的最短路径。D[j]表示顶点i到顶点j的最短路径。初始化的时候,两点之间如果有边,就赋值为其权重,没有边就赋值为无穷大。然后从不在S中的顶点中寻找D数组中的最小值,加入为顶点k,加入S集合。然后更新D信息。D[k] = min{D[k], D[j]+argc[j][k]}后者表示从顶点i到j再到k的路径。重复以上过程n-1次,直到S中包含图中所有顶点为止。

Floyd算法(各顶点之间最短路径,O()

l        时间复杂度为O()

l  算法是一个迭代的过程,允许图中有带负权值的边,但不允许有包含负权值的回路。

l        算法思想:递推产生一个n阶矩阵,,,…,。其中[i][j]表示从顶点i到顶点j,中间顶点的序号不大于k的最短路径长度。从开始,矩阵初始化为就是邻接矩阵,然后进行迭代过程,直到得到,该矩阵就是各顶点之间的最短路径。

拓扑排序(有向图,判断是否有环,O(n+e)

时间复杂度为:O(n+e)

l  有向无环图:DAG图,就是有向图没有环

l  AOV网:用DAG表示一个工程,顶点表示活动,边<i,j>表示活动i必须先于活动j的关系。

l  拓扑排序:由一个有向无环图的顶点构成的序列。要求有两个:

1.    每个顶点仅出现一次

2.    如果图中有A到B的一条路径,那么拓扑排序中必须是AB的顺序。每个DAG图都有一个或者多个拓扑排序

l  算法思想:从DAG图中找一个入度为0的顶点,然后删除该顶点和以它为起点的所有边,然后再剩下的顶点中继续以上操作,直到没有入度为0的顶点或者图为空。如果是前者说明图中一定有环。

l  深度优先搜索也可以得到拓扑序列。

l  拓扑序列唯一,也不能唯一的确认一个图

关键路径(带权有向图)

l  关键路径的本身是不允许有环的,所以第一步一般都是判断是否有环。

l  AOE网:用边表示活动,边的权值表示活动的花销;点表示某个事件。

l  性质:只有某个顶点所代表的事件发生之后,从该顶点出发的有向边所代表的活动才能开始;只有在进入某一顶点的各有向边所代表的活动结束后,该顶点代表的事件才能发生。AOE网中只有一个入度为0【开始顶点/源点】和一个出度为0的顶点【结束顶点/汇点】。

l  关键路径:从源点到汇点的所有路径中,具有最大路径长度的称之为关键路径。完成整个工程的最短时间就是关键路径的长度。

l  关键活动:关键路径上的活动称之为关键活动。如果关键活动不能按时完成的话,整个工期的时间就会延长。

l  事件k发生的最早时间:从前向后推,从源点到事件k顶点的最大路径长度

l  事件k发生的最晚时间:从后向前推,用最早时间减去边上的权重,找的是最小

l  活动i的最早开始时间:<i,j>就是事件i的最早时间

l  活动i的最迟开始时间:<i,j>就是事件j的最晚时间-<i,j>的权值

l  活动i的差值:就是活动i的最迟开始时间-最早开始时间

l  如果活动i的差值为0,说明这个活动就是关键活动。所以算法思想就是:先找出事件和活动的最早和最晚开始时间,然后计算活动的差值,差值为零的就是关键活动,关键活动组成路径上的事件,就是关键事件。

l  注:关键活动决定整个工程的关键,所以可以通过缩短关键活动来加快整个工期。但是也不能随意缩短,因为有可能导致该关键活动变得不是关键活动了;网中的关键路径并不是唯一的,所以缩短某一条关键路径上的关键活动是不能够缩短整个工期的,只有缩短所有关键路径都包含的关键活动才能达到目的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值