数据结构第七章图
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图的遍历方法通常有先深度遍历和先广度遍历两种。 但经常称这两种遍历为深度优先搜索DFS和广度优先搜索 BFS。
7.3.1 深度优先搜索DFS(Depth First Search)
图的深度优先搜索是树的先序遍历的推广,其定义(递归) 如下:
(1)从图G=(V,E)中选任意某个未访问过的顶点vi作为搜索的出发点。 (2)访问vi。 (3)以vi的每一个未被访问过的邻接点w为出发点,深度优先搜索图G。 (4)直至图G中所有与vi有路径相通的顶点都被访问过。 (5)若图G中尚有顶点未曾访问过,则转到(1);否则,搜索结束。
若图G是一个网络,其邻接矩阵 w i j 若 (v i,v j) E,且 (v i,v j)的 权 值 为 w ij A[i ][ j ] 借助于邻接矩阵很容易判定任意两个顶点之间是否有边(或 弧)相连,并容易求得各个顶点的度,操作方便。 (2)邻接矩阵法的特点: 1. 存储空间:对于无向图而言,它的邻接矩阵是对称矩阵, 所以可采用压缩存储法(下三角),其存储空间只需n(n+1)/2。 但对于有向图而言,因为它的弧是有方向的,它的邻接矩阵不 一定是对称矩阵,所以需要n2个存储空间。 2. 便于运算:采用邻接矩阵表示法,便于判定图中任意两个 顶点之间是否有边相连,即根据A[i,j]=0或1来判断。另外还 便于求得各个顶点的度。
路径:在有向图(或无向图)中,如果存在首尾相接并且无重 复边的边序列<v0,v1>,<v1,v2>,…,<vn-2,vn-1> (或 (v0,v1), (v1,v2),…,(vn-2,vn-1)),那么称这个序列是一条从顶点到v0 到vn-1的一条路径,记着(v0,v1,v2,…,vn-2,vn-1)。序列中的 边数称为路径长度。在有向图中,路径是有方向的;而在无 向图中,路径无方向。 简单路径:在一条路径中,若除起点和终点外,所有顶点彼 此各不相同。
A
1 B 4 6 C F I 2 E 8 3
D
5 7
G
H
访问序列为:A、B、E、D、C、G、F、H、I。
广度优先搜索算法:
Procedure bfs(i:1..n);{图用邻接表g表示} Begin create(q); {建队,置队空} write(g[i].v); {访问vi} visited[i]:=true; {标记已经访问的结点} push(q,i); {进队列} while not empty(q) do {广度优先遍历,直到队列空为止,表示所有节点都被 访问过了} begin i:=pop(q); {取顶点,对首元素出队} p:=g[i].link; {取边表指针} while p<>nil do {还有后继顶点} begin if not visited[p^.adj] then begin write(g[p^.adj].v); {访问当前顶点} visited[p^.adj]:=true; push(q,p^,adj); {当前顶点入队} end; p:=p^.next; {从边表中取下一个邻接边} end; end; End;
生成树
1、概念 生成树是一个连通图G的一个极小的连通 子图。包含图G的所有顶点,但只有n-1条边,并 且是连通的。在生成树中,不存在回路路径,但 若在生成树中任意增加一条边,则必构成回路。 一个连通图的生成树不是惟一的,例如,对一个 连通图进行深度优先,在搜索过程中经过的边和 图的顶点,构成深度优先生成树;若进行广度优 先搜索,则构成广度优先生成树。非连通图有若 干个连通分量组成,每一个连通分量都存在生成 树,这样就构成生成森林。
2、 邻接表
(1)存储形式 对一个有n个顶点图的顶点进行编号,顶点的编号从1 到n。图的邻接表存储结构与树的孩子表示法相同。将图G 中每个顶点vi的所有邻接点用一个单链表(邻接点链表)表示, 在vi的邻接点链表中存放vj(有(vi,vj)或<vi,vj>∈E)的编号, 以及其它与该边或弧相关的信息。一个图有n个顶点就有n个 邻接点链表(度为0的顶点,所对应的邻接点链表为空表)。这 n个邻接点链表的头指针又构成一个线性表,用一个指针数 组存储该线性表,这样就构成了图的邻接表的存储结构。例 如,在图7.1中,G1和G2的的邻接表如图7.5所示,图中下标 对应顶点vi的编号。
图的定义和术语
定义: 图(graph):是一种数据结构,由二个集合V和E组成, 记作G=(V,E)。其中V是数据元素(顶点)的非空有限集,E是 V中二元关系(边edge)的集合。树是图的特例,而线性表是 树的特例。 术语: 有向图:图的每条边都是有序顶点对(即边是有方向)。 弧:有向图的边。并将构成该边的有序顶点对用一对 尖括号括起来。如<u,v>∈E,表示从顶点u到顶点v的一条 弧,称u为弧尾或初始点,v为弧头或终端点。并且说v是与 u相邻的顶点,或v是u的邻接点
7.3.2 广度优先搜索BFS(Breadth First Search)
图的广度优先搜索与按层次遍历树相似,定义如下: (1)从图G=(V,E)中选任意某个未访问过的顶点vi作为搜索的出发点。 (2)访问vi。 (3)依次访问vi的各个未曾访问过的邻接点。分别从这些邻接点出发进 行广度优先搜索,直至图中所有与vi有路径相通的顶点都被访问过。 (4)若图中尚有顶点未曾访问过,则转到(1);否则,搜索结束。
网络:若图中每条边或弧都附加一个数值作为权,带权图。
子图:若G1={V1,E1},G2={V2,E2}是两个图,且V2被包含 在V1中,E2被包含在E1中,则称图G2是图G1的子图。
度:无向图中,顶点的度是依附于该顶点的边数。有向图中, 该顶点入边的数目叫入度,该顶点出边的数目叫出度,该顶 点的度就是入度+出度。图中的顶点度数之和等于边数的2倍。
(a)有向图G
(b)图G的三个连通分量
强连通:在有向图G中,若从顶点vi到顶点vj有路径存在, 并且从顶点vj到顶点vi也有路径存在。 强连通图:在有向图G中,若任意二个顶点之间都是强连通 的。 强连通分量:在非强连通的有向图G中,极大强连通 子图称为有向图的强连通分量。如图7.3中,有向图G有两 个强连通分量。 图7.3 有向图及其强连通分量
(a)有向图G (b)图G的二个强连通分量 生成树:在一个有n顶点的连通图G中,存在一个极小的连 通子图G′,G′包含图G的所有顶点,但只有n-1条边,并且 G′是连通的。
图的存储结构
常用的图的存储结构有邻接矩阵、邻接表、十字链表、 多重链表等方法。本节介绍最为常用的邻接矩阵和邻接表 方法。对图的存储结构的选择取决于具体的应用。
2、 最小生成树(最小支撑树)
图7.6 G1的逆邻接表
生成无向带权图的邻接表的算法:
Const n:=图顶点数; e:=图中边数; Type edge=^edgenode; edgenode=record adj:1..n; weight:weighttype next:edge; end; vexnode=record data:datatype; link:edge; end; dajlish=arrar[1..n]of vexnode; Procedure create(var g:dajlish ); Begin for i:=1 to n do begin read(g[i].data); g[i].link:=nil; end; for k:=1 to e do begin read(i,j,w); new(s); s^.adj:=j; s^.weight:=w; s^.next:=g[i].link; g[i].link:=s; End; End;
(a)G1的邻接表
(b)G2的邻接表
图7.5 邻接表存储结构
逆邻接表:对于为网络的图G=(V,E),在node结构中可以添 加一个权值域。而对于有向图,图7.5(a)所示为按G1出度建立 的邻接表,在该邻接表中求每个顶点vi的出度和以vi为尾的弧 方便,但若要求顶点的入度,必须遍历整个邻接表。所以, 有时为了使求顶点vi的入度和以vi为头的弧方便,可以建立该 有向图的逆邻接表,即在vi的邻接点链表中存放vj(有 <vj,vi>∈E)的编号。如图7.6所示为图7.1(a)中G1的逆邻接表。
回路:在一条路径中,若起点和终点是同一顶点。
简单回路:有简单路径组成的回路称为简单回路。 连通:在无向图G中,若从顶点vi到顶点vj有路径存在。
连通图:在无向图G中,若任意二个顶点之间都是连通的.
连通分量:在非连通的无向图G中,极大连通子图(在满足 连通条件下,尽可能多的包含G中的顶点和这些顶点之间 的边) . 如图7.2中,图G有三个连通分量。
1、 邻接矩阵
(1)存储形式 邻接矩阵是用一个二维数组来表示图中顶点间的相邻 关系的数据结构。 设图G=(V,E),有n≥1个顶点,则所对应图G的邻接矩 阵A是按如下定义的一个n×n的二维数组。 若(vi ,v j ) E (对有向图为 vi ,vj E) 1 A[i][ j ] 否则 0
与树的遍历相同,把按一定的规律沿着图中的边访问 图的每个顶点,并且使每一个顶点只被访问一次的过程称 为图的遍历。
因为在图中任意两个顶点之间都可能有关系。为保证 每一个顶点只被访问一次,必须对访问过的顶点进行标记, 一般是用一个辅助数组visit[i]作为对顶点的标记。当顶点vi 未被访问,visit[i]值为0;当顶点vi已被访问,则visit[i]值为 1。
其中实箭头代表访问方向,虚箭头代表回溯方向,箭头旁边的数 字代表搜索顺序,A为起始顶点。 8 A D G 9 1 1 1 16 7 14 0 3 6 B E H 15 2 5 1 12 C 3 4
1
F
I
访问序列为:A、B、C、F、E、G、D、H、I。
深度优先搜索算法:
Procedure dfs(i:1..n);{图用邻接表存储,其他方式的存储只 需稍作修改,g[i]为表头结点表} Begin write(g[i].v);{输出是最为简单的访问方式} visited[i]:=true; p:=g[i].link; while p<>nil do begin j:=p^.adj;{j为i的一个后继} if not visited[j] then dfs(j);{递归} p:=p^.next; {回溯} end; end/;
•图的定义和术语 •图的存储结构 •图的遍历 •生成树 •最短路径 •拓扑排序 习题
图是一种较线性表和树更为复杂的数据结构。 在线性表中,数据元素之间有线性关系,每一个数 据元素只有一个直接前驱和一个直接后续;在树形 结构中,数据元素之间有着明显的层次关系,即每 一个数据元素有一个直接前驱(双亲)和零个或多个 直接后续(孩子);而在图形结构中,结点之间的关 系是任意的,图中任意两个数据元素之间都可能相 关。由此,图的应用极为广泛。例如,城市间的最 短路径,火车的联票,交通网的计划,战场上的运 输问题,庞大的施工进度图等都是图的应用。
思考并实现:
1、分别在无向图和有向图的邻接表上统计各顶点的 度(有向图为入度和出度)。 2、统计图(有向图和无向图)的顶点度数和。
2、 边集数组表示法
边 数
起 点 终 点 权
v1 4
5 v5 2 1 7 v4 v3
1
1 2 4
2
1 5 5
3
2 3 3
4
2 5 2
5
3 4 1
6
4 5 7
v2
ຫໍສະໝຸດ Baidu
3
7.3 图的遍历
例如,图7.1(a)所示的为有向图,它是由集合 V={v0,v1,v2,v3} E={<v0,v1>,<v0,v2>,<v2,v3>,<v3,v0>} 组成的。
图7.1 (a)有向图G1
无向图:图的每条边是无方向的,有<u,v>∈E,必有<v,u>∈E。 即用圆括号括起来 (u,v)∈E表示边,并且,u和v互称为邻接点 例如,图7.1(b) 为无向图,它是由集合 V={ v0,v1,v2,v3,v4 } E={(v0,v1),(v0,v3),(v1,v2),(v1,v4),(v2,v3) ,(v2,v4)} 组成的。
7.3.1 深度优先搜索DFS(Depth First Search)
图的深度优先搜索是树的先序遍历的推广,其定义(递归) 如下:
(1)从图G=(V,E)中选任意某个未访问过的顶点vi作为搜索的出发点。 (2)访问vi。 (3)以vi的每一个未被访问过的邻接点w为出发点,深度优先搜索图G。 (4)直至图G中所有与vi有路径相通的顶点都被访问过。 (5)若图G中尚有顶点未曾访问过,则转到(1);否则,搜索结束。
若图G是一个网络,其邻接矩阵 w i j 若 (v i,v j) E,且 (v i,v j)的 权 值 为 w ij A[i ][ j ] 借助于邻接矩阵很容易判定任意两个顶点之间是否有边(或 弧)相连,并容易求得各个顶点的度,操作方便。 (2)邻接矩阵法的特点: 1. 存储空间:对于无向图而言,它的邻接矩阵是对称矩阵, 所以可采用压缩存储法(下三角),其存储空间只需n(n+1)/2。 但对于有向图而言,因为它的弧是有方向的,它的邻接矩阵不 一定是对称矩阵,所以需要n2个存储空间。 2. 便于运算:采用邻接矩阵表示法,便于判定图中任意两个 顶点之间是否有边相连,即根据A[i,j]=0或1来判断。另外还 便于求得各个顶点的度。
路径:在有向图(或无向图)中,如果存在首尾相接并且无重 复边的边序列<v0,v1>,<v1,v2>,…,<vn-2,vn-1> (或 (v0,v1), (v1,v2),…,(vn-2,vn-1)),那么称这个序列是一条从顶点到v0 到vn-1的一条路径,记着(v0,v1,v2,…,vn-2,vn-1)。序列中的 边数称为路径长度。在有向图中,路径是有方向的;而在无 向图中,路径无方向。 简单路径:在一条路径中,若除起点和终点外,所有顶点彼 此各不相同。
A
1 B 4 6 C F I 2 E 8 3
D
5 7
G
H
访问序列为:A、B、E、D、C、G、F、H、I。
广度优先搜索算法:
Procedure bfs(i:1..n);{图用邻接表g表示} Begin create(q); {建队,置队空} write(g[i].v); {访问vi} visited[i]:=true; {标记已经访问的结点} push(q,i); {进队列} while not empty(q) do {广度优先遍历,直到队列空为止,表示所有节点都被 访问过了} begin i:=pop(q); {取顶点,对首元素出队} p:=g[i].link; {取边表指针} while p<>nil do {还有后继顶点} begin if not visited[p^.adj] then begin write(g[p^.adj].v); {访问当前顶点} visited[p^.adj]:=true; push(q,p^,adj); {当前顶点入队} end; p:=p^.next; {从边表中取下一个邻接边} end; end; End;
生成树
1、概念 生成树是一个连通图G的一个极小的连通 子图。包含图G的所有顶点,但只有n-1条边,并 且是连通的。在生成树中,不存在回路路径,但 若在生成树中任意增加一条边,则必构成回路。 一个连通图的生成树不是惟一的,例如,对一个 连通图进行深度优先,在搜索过程中经过的边和 图的顶点,构成深度优先生成树;若进行广度优 先搜索,则构成广度优先生成树。非连通图有若 干个连通分量组成,每一个连通分量都存在生成 树,这样就构成生成森林。
2、 邻接表
(1)存储形式 对一个有n个顶点图的顶点进行编号,顶点的编号从1 到n。图的邻接表存储结构与树的孩子表示法相同。将图G 中每个顶点vi的所有邻接点用一个单链表(邻接点链表)表示, 在vi的邻接点链表中存放vj(有(vi,vj)或<vi,vj>∈E)的编号, 以及其它与该边或弧相关的信息。一个图有n个顶点就有n个 邻接点链表(度为0的顶点,所对应的邻接点链表为空表)。这 n个邻接点链表的头指针又构成一个线性表,用一个指针数 组存储该线性表,这样就构成了图的邻接表的存储结构。例 如,在图7.1中,G1和G2的的邻接表如图7.5所示,图中下标 对应顶点vi的编号。
图的定义和术语
定义: 图(graph):是一种数据结构,由二个集合V和E组成, 记作G=(V,E)。其中V是数据元素(顶点)的非空有限集,E是 V中二元关系(边edge)的集合。树是图的特例,而线性表是 树的特例。 术语: 有向图:图的每条边都是有序顶点对(即边是有方向)。 弧:有向图的边。并将构成该边的有序顶点对用一对 尖括号括起来。如<u,v>∈E,表示从顶点u到顶点v的一条 弧,称u为弧尾或初始点,v为弧头或终端点。并且说v是与 u相邻的顶点,或v是u的邻接点
7.3.2 广度优先搜索BFS(Breadth First Search)
图的广度优先搜索与按层次遍历树相似,定义如下: (1)从图G=(V,E)中选任意某个未访问过的顶点vi作为搜索的出发点。 (2)访问vi。 (3)依次访问vi的各个未曾访问过的邻接点。分别从这些邻接点出发进 行广度优先搜索,直至图中所有与vi有路径相通的顶点都被访问过。 (4)若图中尚有顶点未曾访问过,则转到(1);否则,搜索结束。
网络:若图中每条边或弧都附加一个数值作为权,带权图。
子图:若G1={V1,E1},G2={V2,E2}是两个图,且V2被包含 在V1中,E2被包含在E1中,则称图G2是图G1的子图。
度:无向图中,顶点的度是依附于该顶点的边数。有向图中, 该顶点入边的数目叫入度,该顶点出边的数目叫出度,该顶 点的度就是入度+出度。图中的顶点度数之和等于边数的2倍。
(a)有向图G
(b)图G的三个连通分量
强连通:在有向图G中,若从顶点vi到顶点vj有路径存在, 并且从顶点vj到顶点vi也有路径存在。 强连通图:在有向图G中,若任意二个顶点之间都是强连通 的。 强连通分量:在非强连通的有向图G中,极大强连通 子图称为有向图的强连通分量。如图7.3中,有向图G有两 个强连通分量。 图7.3 有向图及其强连通分量
(a)有向图G (b)图G的二个强连通分量 生成树:在一个有n顶点的连通图G中,存在一个极小的连 通子图G′,G′包含图G的所有顶点,但只有n-1条边,并且 G′是连通的。
图的存储结构
常用的图的存储结构有邻接矩阵、邻接表、十字链表、 多重链表等方法。本节介绍最为常用的邻接矩阵和邻接表 方法。对图的存储结构的选择取决于具体的应用。
2、 最小生成树(最小支撑树)
图7.6 G1的逆邻接表
生成无向带权图的邻接表的算法:
Const n:=图顶点数; e:=图中边数; Type edge=^edgenode; edgenode=record adj:1..n; weight:weighttype next:edge; end; vexnode=record data:datatype; link:edge; end; dajlish=arrar[1..n]of vexnode; Procedure create(var g:dajlish ); Begin for i:=1 to n do begin read(g[i].data); g[i].link:=nil; end; for k:=1 to e do begin read(i,j,w); new(s); s^.adj:=j; s^.weight:=w; s^.next:=g[i].link; g[i].link:=s; End; End;
(a)G1的邻接表
(b)G2的邻接表
图7.5 邻接表存储结构
逆邻接表:对于为网络的图G=(V,E),在node结构中可以添 加一个权值域。而对于有向图,图7.5(a)所示为按G1出度建立 的邻接表,在该邻接表中求每个顶点vi的出度和以vi为尾的弧 方便,但若要求顶点的入度,必须遍历整个邻接表。所以, 有时为了使求顶点vi的入度和以vi为头的弧方便,可以建立该 有向图的逆邻接表,即在vi的邻接点链表中存放vj(有 <vj,vi>∈E)的编号。如图7.6所示为图7.1(a)中G1的逆邻接表。
回路:在一条路径中,若起点和终点是同一顶点。
简单回路:有简单路径组成的回路称为简单回路。 连通:在无向图G中,若从顶点vi到顶点vj有路径存在。
连通图:在无向图G中,若任意二个顶点之间都是连通的.
连通分量:在非连通的无向图G中,极大连通子图(在满足 连通条件下,尽可能多的包含G中的顶点和这些顶点之间 的边) . 如图7.2中,图G有三个连通分量。
1、 邻接矩阵
(1)存储形式 邻接矩阵是用一个二维数组来表示图中顶点间的相邻 关系的数据结构。 设图G=(V,E),有n≥1个顶点,则所对应图G的邻接矩 阵A是按如下定义的一个n×n的二维数组。 若(vi ,v j ) E (对有向图为 vi ,vj E) 1 A[i][ j ] 否则 0
与树的遍历相同,把按一定的规律沿着图中的边访问 图的每个顶点,并且使每一个顶点只被访问一次的过程称 为图的遍历。
因为在图中任意两个顶点之间都可能有关系。为保证 每一个顶点只被访问一次,必须对访问过的顶点进行标记, 一般是用一个辅助数组visit[i]作为对顶点的标记。当顶点vi 未被访问,visit[i]值为0;当顶点vi已被访问,则visit[i]值为 1。
其中实箭头代表访问方向,虚箭头代表回溯方向,箭头旁边的数 字代表搜索顺序,A为起始顶点。 8 A D G 9 1 1 1 16 7 14 0 3 6 B E H 15 2 5 1 12 C 3 4
1
F
I
访问序列为:A、B、C、F、E、G、D、H、I。
深度优先搜索算法:
Procedure dfs(i:1..n);{图用邻接表存储,其他方式的存储只 需稍作修改,g[i]为表头结点表} Begin write(g[i].v);{输出是最为简单的访问方式} visited[i]:=true; p:=g[i].link; while p<>nil do begin j:=p^.adj;{j为i的一个后继} if not visited[j] then dfs(j);{递归} p:=p^.next; {回溯} end; end/;
•图的定义和术语 •图的存储结构 •图的遍历 •生成树 •最短路径 •拓扑排序 习题
图是一种较线性表和树更为复杂的数据结构。 在线性表中,数据元素之间有线性关系,每一个数 据元素只有一个直接前驱和一个直接后续;在树形 结构中,数据元素之间有着明显的层次关系,即每 一个数据元素有一个直接前驱(双亲)和零个或多个 直接后续(孩子);而在图形结构中,结点之间的关 系是任意的,图中任意两个数据元素之间都可能相 关。由此,图的应用极为广泛。例如,城市间的最 短路径,火车的联票,交通网的计划,战场上的运 输问题,庞大的施工进度图等都是图的应用。
思考并实现:
1、分别在无向图和有向图的邻接表上统计各顶点的 度(有向图为入度和出度)。 2、统计图(有向图和无向图)的顶点度数和。
2、 边集数组表示法
边 数
起 点 终 点 权
v1 4
5 v5 2 1 7 v4 v3
1
1 2 4
2
1 5 5
3
2 3 3
4
2 5 2
5
3 4 1
6
4 5 7
v2
ຫໍສະໝຸດ Baidu
3
7.3 图的遍历
例如,图7.1(a)所示的为有向图,它是由集合 V={v0,v1,v2,v3} E={<v0,v1>,<v0,v2>,<v2,v3>,<v3,v0>} 组成的。
图7.1 (a)有向图G1
无向图:图的每条边是无方向的,有<u,v>∈E,必有<v,u>∈E。 即用圆括号括起来 (u,v)∈E表示边,并且,u和v互称为邻接点 例如,图7.1(b) 为无向图,它是由集合 V={ v0,v1,v2,v3,v4 } E={(v0,v1),(v0,v3),(v1,v2),(v1,v4),(v2,v3) ,(v2,v4)} 组成的。