图(概念、存储、遍历、应用)

基本概念

有向图:顶点之间的边是有向的
无向图:顶点之间的边是无向的
简单图:没有重复的边,没有到自身的边


完全图:有n(n-1)/2条边的无向图(每一个顶点都与其他顶点两两相连,没有方向)
有向完全图:有n(n-1)条边的有向图(每一个顶点都与其他顶点两两相连,有方向,任意两点之间存在方向相反的两条弧)
在这里插入图片描述


子图:取原图中的一些边和顶点组成的图就是子图,此时边两头必须得连接顶点。
生成子图:包含原图中所有顶点,部分边的图,即该图的生成子图
在这里插入图片描述


针对于无向图
连通图:任意两个顶点都是连通的(任意两顶点间都有通路)
连通分量:无向图中的极大连通子图
在这里插入图片描述
针对于有向图
强连通图:任意一对顶点w、v,w到v与v到w都有路径
强连通分量:有向图中的极大强连通子图

在这里插入图片描述


生成树:连通图的生成树包含图中全部顶点n,以及n-1条边的极小连通子图
生成森林:非连通图中,连通分量的生成树构成了非连通图的生成森林。
最小生成树:一个带权连通无向图中,有很多生成树,其中权值最小的树就是最小生成树
在这里插入图片描述


简单路径:顶点不出现重复的路径
最短路径:带权路径长度最短的路径就是最短路径
关键路径:带权有向图中,从开始顶点到结束顶点的所有路径中,具有最大长度的路径就是关键路径


有向树:一个顶点入度为0,其余顶点入度都是1的有向图

存储方式

邻接矩阵法

邻接矩阵存储:是指用一个一维数组存储顶点信息,用一个二维数组存储边的信息(各低昂点之间的邻接关系)。
不带权值的邻接矩阵:
A[i][j] = 1 ;表示 vi 到 vj 顶点之间有一条边(vi,vj),或一条弧<Vi,vj>
A[i][j] = 0;表示 vi 到 vj 之间不存在边或弧
带权值的邻接矩阵:
A[i][j] = wij ;表示 vi 到 vj 之间有边或弧,存储权值
A[i][j] = 0 或∞ ;表示 vi 到 vj 之间不存在边或弧

邻接表法

邻接表就是对每一个顶点建立一个单链表,单链表中的元素是与该顶点相连的元素。

在这里插入图片描述

十字链表

有向图的一种链式存储结构
有向图的每一个顶点是一个结点,每一条弧也是一个结点

顶点结点包含3个域:
data域:存放顶点数据信息,
firstin域(入弧):存储以该顶点为弧头(终端点)的第一个弧结点,
firstout域(出弧):存储以该顶点为弧尾(初始点)的第一个弧结点。

datafirstinfirstout

弧结点包含5个域:
tailvex尾域(弧尾):存储弧尾顶点在图中的位置
headvex头域(弧头):存储弧头顶点在途中的位置
hlink链域:指向与该弧头相同的下一条弧
tlink链域:指向与该弧尾相同的下一条弧
info域:存放弧的数据信息(权值)

tailvexheadvexhlinktlinkinfo

看下面例子分析:
在这里插入图片描述
在这里插入图片描述
分析可知顶点可能有多条出弧,多条入弧,所以十字链表表示方式不唯一

邻接多重表

无向图的一种链式存储结构

每条边用一个结点表示:6个域
mark标志域:标记该条边是否被搜索过
ivex域、jvex域:表示该边的两个顶点在图中的位置
ilink域:指向下一条有顶点ivex的边
jlink域:指向下一条有顶点jvex的边
info域:指向和边相关的各种信息的指针域

markivexilinkjvexjlinkinfo

顶点用一个结点表示:两个域
data域:存储数据信息
firstedge域:指示第一条依附于该顶点的边。

datafirstedge

在这里插入图片描述

遍历

深度优先搜索(Depth-First-Search,DFS)

类似于树的先序遍历。

思想:
1、从某一顶点v开始,先访问顶点v,然后从v出发,访问与v邻接且未被访问的任一顶点w1,再访问与w1邻接且未被访问的任一顶点w2,以此类推。
2、当不能像下访问时,依次回退到最近被访问的顶点,若该顶点还有邻接顶点未被访问过,则从该点开始继续步骤1中的搜索过程,直到所有顶点被访问。

DFS算法是一个递归算法,需要借助一个递归工作栈,时间复杂度为O(|v|)。

广度优先搜索(Breadth-First-Search,BFS)

类似于二叉树的层序遍历。

思想:
1、从某一顶点v开始,访问顶点v,
2、依次访问顶点v的各个未被访问过的邻接顶点w1,w2…,
3、再依次访问w1,w2…的所有未被访问过的邻接顶点,直到所有顶点被访问。

BFS算法需要借助一个辅助队列,所有顶点都需要入队一次,空间复杂度O(|v|)。

性能比较(时间复杂度)

-BFSDFS
邻接矩阵O(|V|2)O(|V|2)
邻接表O(|V| + |E|)O(|V| + |E|)

无论BFS还是DFS,
采用邻接矩阵存储方式,查找每个顶点的邻接点所需时间为O(|v|),总时间为O(|V|2);
采用邻接表存储方式,每个顶点需要访问一次,每条边需要访问一次,总时间复杂度为O(|V|+|E|)。

基本应用

最小生成树

Prim算法(普里姆算法)

从某一顶点开始构建生成树,每次将代价最小的新结点纳入生成树,直到所有顶点都纳入为止。

Prim算法时间复杂度O(|V|2),不依赖边E,适合求解边稠密的图的最小生成树。

Prim算法最小生成树:
在这里插入图片描述

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

每次选择一条权值最小的边,使边两头连通(已连通的就不选),直到所有结点都连通。

时间复杂度O(|E|log|E|),适合边稀疏而顶点较多的图。

Kruskal算法最小生成树:

最短路径

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

Dijkstra算法计算单源最短路径(求图中某一顶点到其他各个顶点的最短路径),主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

思路:
借助两个数组:
dist[]:记录从源点到其他各顶点的最短路径长度,初始dist[0]为0(源点到源点的距离为0)。
path[]:记录最短路径上到此顶点的前驱结点

在这里插入图片描述
1⃣️V0为起始点。得到初始数组:
V0到V1距离10,
V0到V2距离∞,
V0到V3距离∞,
V0到V4距离5;

i01234
dist[i]0105

V0最短路径前驱:没有为-1,
V1最短路径前驱:V0,
V2最短路径前驱:没有为-1,
V3最短路径前驱:没有为-1,
V4最短路径前驱:V0

i01234
path[i]-10-1-10

2⃣️循环遍历所有结点,找到还没确定最短路径,且dist值最小的顶点,V4,即V4到V0的最短距离为5;

查看V4顶点,与之相关对有V1、V2、V3顶点,
V4到V1对距离为3,则从V0-V4-V1得到路径长度为8,比1⃣️中V1-V0距离更短;
V4到V2的距离为9,则V0-V4-V2距离是14
V4到V3点距离为2,则V0-V4-V3距离为7
得到数组:

V0到V1距离8,
V0到V2距离14,
V0到V3距离7,
V4到V0距离5;

i01234
dist[i]081475

V0最短路径前驱:没有为-1,
V1最短路径前驱:V4,
V2最短路径前驱:V4,
V3最短路径前驱:V4,
V4最短路径前驱:V0

i01234
path[i]-14440

3⃣️循环2⃣️的操作,循环遍历所有结点,找到还没确定最短路径,且dist值最小的顶点,V3;
查看V3顶点,与之相关的有V0、V2顶点,
V0已经确定最短路径,不需要再处理,

V3到V2对距离为6,则从V0-V4-V3-V2得到路径长度为13,比2⃣️中V0-V4-V2距离更短;
得到数组:

V0到V1距离8,
V0到V2距离13,
V0到V3距离7,
V4到V0距离5;

i01234
dist[i]081375

V0最短路径前驱:没有为-1,
V1最短路径前驱:V4,
V2最短路径前驱:V3,
V3最短路径前驱:V4,
V4最短路径前驱:V0

i01234
path[i]-14340

4⃣️循环2⃣️的操作,循环遍历所有结点,找到还没确定最短路径,且dist值最小的顶点,V1;
查看V1顶点,与之相关的有V2、V4顶点,

V1到V2对距离为1,则从V0-V4-V1-V2得到路径长度为9,比3⃣️中V0-V4-V3-V2距离更短;
得到数组:

V0到V1距离8,
V0到V2距离9,
V0到V3距离7,
V4到V0距离5;

i01234
dist[i]08975

V0最短路径前驱:没有为-1,
V1最短路径前驱:V4,
V2最短路径前驱:V1,
V3最短路径前驱:V4,
V4最短路径前驱:V0

i01234
path[i]-14140

5⃣️重复2⃣️的步骤,找到顶点V2,为找到未确定最短路径的顶点,不需要再处理。

V0-V1最短路径长度为8,路径:V0-V4-V1
V0-V2最短路径长度为9,路径:V0-V4-V1-V2
V0-V3最短路径长度为7,路径:V0-V4-V3
V0-V4最短路径长度为5,路径:V0-V4

Floyd算法(弗洛伊德算法)

求每对顶点间的最短路径。

思想:
1⃣️初始状态,路径没有中转结点,所得到的两顶点间的最短路径,得到方阵A-1也就是图的邻接矩阵
2⃣️允许V0是中转点,所得到两顶点间的最短路径,得到方阵A0
3⃣️允许V0、V1是中转点,所得到两顶点之间的最短路径,得到方阵A1

以此类推,Floyd算法是一个迭代的过程,每迭代一次,在两点间最短路径上多增加一个中转点,经过n次迭代之后,得到的方阵就是最短路径的方阵。

在这里插入图片描述

拓扑排序

AOV网:顶点表示活动的右向图网络,不允许存在环路,没有权值
拓扑排序:是一个有向无环图顶点组成的序列,每个顶点出现且只出现一次,若序列中A在B的前面,则图中不存在B到A的路径。

思路:
1、从AOV网中选择一个没有前驱的顶点并输出
2、从网中删除该顶点和所有以它为起点的有向边
3、重复1、2直到AOV网为空或当前网中不存在无前驱的顶点为止(后者说明有向图中必存在环)

在这里插入图片描述

关键路径

AOE网:顶点表示事件,用边表示活动的网络,边有权值
AOE网中仅有一个入度为0的点,表示工程的开始,是开始顶点(源点);仅有一个出度为0的顶点,表示工程的结束,是结束顶点(汇点)

关键路径:从源点到汇点的所有路径中,具有最大路径长度的路径
关键活动:关键路径上的活动
关键路径长度:完成整个工程的最短时间就是关键路径长度

事件vk最早发生时间ve(k):从源点v1到顶点vk的最长路径长度
事件vk最晚发生时间vl(k):不推迟整个工期前提下,保证其后继事件可以在最迟时间发生,该时间最迟必须发生的时间
活动ai的最早开始时间e(i):指活动弧起点所表示事件的最早发生时间
活动ai的最晚开始时间e(i):指活动弧终点所表示事件的最迟发生时间与该活动所需时间之差
一个活动ai最迟开始时间l(i)与最早开始时间e(i)的差额d(i) = l(i) - e(i):是指该活动完成的时间余量,即在不增加完成工期所需的总时间情况下,活动ai可以拖延的时间。

在这里插入图片描述

关键路径是源点到汇点最长的路径:v1 - v3 - v4 - v6;长度为8

事件最早开始时间:v2事件当a1活动结束后就开始,时间为3;v3事件当a2活动结束后就开始,时间为2;v4事件当a2活动和a5活动结束后就开始,时间为6;v5事件当a1活动和a4结束后就开始,时间为6;v6事件当a2活动、a5活动和a7活动结束后就开始,时间为8;
事件最晚开始时间:v6完成需要时间8,逆推,v5最晚需要在7时完成;v4最晚需要在6时完成;v2最晚需要在4完成;v3最晚需要在2时完成。

v1v2v3v4v5v6
事件最早发生时间 - ve(i)032668
事件最晚发生时间 - vl(i)042678

活动最早开始时间:活动最早开始时间等于该弧起点事件的最早开始时间e() = ve()
活动最晚开始时间:活动的最迟开始时间等于该弧终点事件最晚开始时间减去该弧持续的时间

a1a2a3a4a5a6a7a8
活动最早开始时间 - e(i)00332266
活动最晚开始时间 - l(i)10442567
活动最晚与最早时间差 - l(i) - e(i)10110301
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值