《数据结构(Python语言描述)》第8章 图
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图8-1 图
8.1.2 图的基本用语(无向边、无向图、有向边、有向图)
4
无向图:图的每条边都没有方向(无向边),即边的2个顶点没有次序关系。(A,B), (B,A)是同一条边。
有向图:图的每条边都是有方向的(有向边),即边的2个顶点有次序关系。<E,F>,<F,E> 是2条边。
图8-1 图
8.1.2 图的基本用语(无向完全图、有向完全图)
0
0
12
1
3
3
图8-13 无向图
0
0
2
12
3
3
图8-14 子图
8.1.2 图的基本用语(生成树)
11
生成树:一个n个顶点的连通图的生成树是一个极小连通子图,它含有图中所有的顶点, 但具有足以构成一棵树的n-1条边。
图8-15 连通图
图8-16 生成树
8.1.2 图的基本用语(连通图、连通分量)
class Edge(object): def __init__(self,adjVex): self.adjVex = adjVex self.nextEdge = None
8.2.2 邻接表
22
对于无权图来说,边节点有两个域,一个是邻接点域adjVex,存储该顶点的邻接点在 顶点数组中的下标值。另一个是指针域nextEdge,存储指向边表中下一个节点的指针
7
顶点的度、入度、出度: 有向图中顶点v的度分为出度和入度,出度是该顶点的出边的数目,记为OD
(v)。入度是该顶点的入边的数目,记为ID(v)。有向图中顶点v的度等于其 出度加入度之和。
无向图中,顶点的度为以该顶点为一个端点的边的数目。记为D(v)。
图8-7 有向图
图8-8 无向图
8.1.2 图的基本用语(权、带权图)
16
• 有向带权图
在有向带权图中,假设存储顶点的一维数组为vertex,存储边的二维数组 为edges,若顶点i到顶点j是连通的,则有edges[i][j]=Wij,Wij表示顶点i和顶 点j之间边的权值;若顶点i到顶点j是不连通的,则有edges[i][j]=∞。有向有 权图的邻接矩阵示例如图所示。
8.2.2 十字链表
26
在邻接矩阵中,我们可以很方便求出每个顶点的出度和入度。但是,在邻接表 中,不方便获取顶点的入度。如果用邻接表的方式,又能达到比较方便获取每 个顶点的出度和入度。我们采用十字链表的存储方式,来实现图的存储。十字 链表就是图的邻接表和图的逆邻接表的结合。
邻接表需要一个一维数组来保存顶点。构建十字链表时,通过采用顶点节点和 边节点,来创建一个十字链表。
环:路径中第一个顶点和最后一个顶点相同,称之为环。
路径长度:在带权图中,路径长度指的是路径上各边的权之和。在非带权图中,路径 长度指的是路径上边的数目。
图8-11 路径(A,B,C,D,E),长度为5
图8-12 存在环的图
8.1.2 图的基本用语(子图)
10
子图:若图G=(V,E),G'=(V',E'),如果V' ⊆ V并且E' ⊆ E,则称图G'是G的子图。例 如图8-15所示三个图均为图8-14所示图的子图。其中,如果V'=V并且E'⊆E,则称图 G'是G的生成子图
12
在无向图中,如果任意2个顶点之间都有路径,则称该无向图是连通图。无向图的极大连通 子图称为连通分量。
图8-17 非连通图
图8-18 极大连通子图
8.1.2 图的基本用语(强连通图、强连通分量)
13
在有向图中,如果任意2个顶点之间都存在可到达的路径,则称该有向图是强连通图。 有向图的极大连通子图称为该有向图的强连通分量。
8.3 图的遍历
29
图的遍历,就是从图中某一顶点出发,访问图中其余顶点,使每个顶点仅且被 访问一次。
图的遍历方法有深度优先遍历和广度优先遍历。
8.3.1 深度优先遍历
30
1.算法思想
步骤1: 从图的某个顶点vi出发,访问此顶点。
步骤2:
若当前访问的顶点vi的邻接点vj有未被访问的 ,则任选一个继续访问;若当前访问的顶点vi 的邻接点vj皆被访问过,则回溯到最近访问过 的顶点,直至初始顶点的所有邻接点都访问完
数据结构 (Python语言描述)
第8章 图
8.1.1 图的定义
3
图是由顶点集合(vertex)及顶点间的关系集合组成 的一种数据结构: Graph=( V, E ) 其中
V = { x | x 某个数据对象} 是顶点的有穷非空集合; E = {(x, y) | x, y V } 或 E = {<x, y> | x, y V && Path (x, y)} 是顶点之间关系的有穷集合,也叫做边(edge)集合。
图8-25 无向无权图
图8-26 左图的邻接表表示
8.2.2 邻接表
24
左图是一个无向有权图,边节点只有3个域,分别是adjVex、weight和nextEdge。用邻 接表存储方式将其展示出来如右图所示。
图8-27 无向有权图
图8-28 左图的邻接表表示
8.2.2 邻接表
基本操作
+
-
÷
×
25
十字链表边节点Edge类 class Edge(object):
def __init__(self, headvex , tailvex): self.headvex = headvex self.tailvex = tailvex self.hlink = None self.tlink = None
有向无权图
在有向无权图中,假设存储顶点的一维数组为vertex,存储边的二维数组为edges,若 顶点i到顶点j是连通的,则有edges[i][j]=1;若顶点i到顶点j是不连通的,则有 edges[i][j]=0。有向无权图的邻接矩阵示例如图所示。
图8-21 向无权图的顶点数组及其邻接矩阵
8.2.1 邻接矩阵
图8-19 有向图
图8-20 强连通分量
8.2 图的存储结构
14
图的存储结构分别有邻接矩阵、 邻接表、十字链表、邻接多重表和 边表。在本章节中,主要讲解邻接 矩阵、邻接表、十字链表。
8.2.1 邻接矩阵
15
邻接矩阵用二维数组来存储图的信息。假设图的顶点有n个,则可以用大小为n*n的二 维数组来存储每两个顶点之间的边的信息。
class Vertex(object): def __init__(self, data): self.data = data self.firstEdge = None
8.2.2 邻接表
21
对于无权图来说,边节点有两个域,一个是邻接点域adjVex,存储该顶点的邻接点在 顶点数组中的下标值。另一个是指针域nextEdge,存储指向边表中下一个节点的指针
8.2.2 十字链表
27
顶点节点的有三个域,一个是值域data,存储顶点的数值,一个是指针域firstIn,一个指向 以该顶点为弧头的顶点。一个是指针域firstOut,指向以该顶点为弧尾的顶点,十字链表顶点节 点的存储结构如图所示。
十字链表头顶点Vertex类 class Vertex(object):
5
无向完全图:在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。
有向完全图:在有向图中,如果任意两个顶点之间都存在方向相反的两条弧,则称该图 为有向完全图,否则为非有向完全图。
图8-2 无向完全图
图8-3 非有向完全图
图8-4 有向完全图
8.1.2 图的基本用语(邻接、依附)
6
邻接、依附: 无向图中,对于任意两个顶点vi和vj,若存在边(vi,vj),则称顶点vi和顶点vj
32
规定顶点1作为起点,从顶点1开始访问,访问完之后将顶点1入栈;接着访问顶点1其中一 个未被访问的邻接点,已被访问过的顶点用黑色标记。
图8-30 访问图中的顶点1并将顶点1入栈
8.3.1 深度优先遍历
33
访问顶点2的邻接点顶点3,并且将顶点3入栈。 访问顶点3的邻接点顶点4,并且将顶点4入栈。
def __init__(self,data): self.data = data self.firstIn = None self.firstOut = None
8.2.2 十字链表
28
边节点有4个域,两个值域,两个指针域。两个值域分别是headvex,tailvex,分别存储弧的 头顶点和尾顶点的位置。两个指针域分别是hlink,tlink,分别存储指向弧头和弧尾相同的节点, 十字链表节点的存储结构如图所示。
获取顶点在顶点集合中的下标值:获取顶点在顶点数组中的 下标值,如果顶点在顶点数组中,返回下标值,如果顶点不 在数组中,返回-1。 将边添加到顶点v的边表表尾:将新边添加到顶点v的边表表 尾,若是顶点v的下一条邻接边不为空,则继续遍历;若是顶 点v的下一条邻接表为空,则添加新边。 添加边节点:获取弧头弧尾在表头数组中的下标值,再构造 新边节点,最后将新边节点添加到弧尾的边集中。 求顶点出度:通过遍历顶点v的边集,每访问一条依附在顶点 v的边时,出度数加1。
图8-22 有向有权图的顶点数组及其邻接矩阵
8.2.1 邻接矩阵
17
• 无向无权图
在无向无权图中,假设存储顶点的一维数组为vertex,存储边的二维数组 为edges,若顶点i到顶点j是连通的,则有edges[i][j]=1;若顶点i到顶点j是 不连通的,则有edges[i][j]=0。无向无权图的邻接矩阵示例如图所示。
图8-23 无向无权图的顶点数组及其邻接矩阵
8.2.1 邻接矩阵
18
• 无向有权图
在无向有权图中,假设存储顶点的一级数组为vertex,存储边的二维数组为edges, 若顶点i到顶点j是连通的,则有edges[i][j]=Wij,Wij表示顶点i和顶点j之间边的权值; 若顶点i到顶点j是不连通的,则有edges[i][j]=∞。无向有权图的邻接矩阵示例如图 所示。
8
权:图的边上的具有特定含义的数值称为权。 带权图:图的每条边都带有一个权,这样的图称为带权图,也称网。
4 AD 592
B 3C
图8-9 有向带权图
A 52
BC 3
图8-10 无向带权图
8.1.2 图的基本用语(路径、简单路径、环、路径长度)
9
路径、简单路径:在图中,路径是由边的顺序连接的一系列顶点。简单路径是图中的 路径没有重复顶点的
图8-24 无向有权图的顶点数组及其邻接矩阵
8.2.1 邻接矩阵
基本操作
+
-
÷
×
19
获取顶点在矩阵中的下标值:获取顶点在顶点数组中的下标 值,如果顶点在顶点数组中,返回下标值,如果顶点不在数 组中,返回-1。 添加边节点:通过获取边的弧尾,边的弧尾在二维矩阵中位 置,然后将二维矩阵中对应的值置为1。 求顶点入度:取顶点的入度,就是求取该顶点在二维矩阵中 所在的行,顶点的入度即该行中数值为1 的个数。 求顶点出度:计算顶点所在矩阵中的行中有多少个1,数值1 的个数即为顶点的出度数。
class Edge(object): def __init__(self,adjVex, weight): self.adjVex = adjVex self.nextEdge = None self.weight = weight
5G
8.2.2 邻接表
23
左图是一个无向无权图,邻接表中边节点只有两个域,分别是adjVex和nextEdge,右 图是左图的邻接表表示。
8.2.2 邻接表
20
邻接矩阵中,我们可以很方便求出每个顶点的出度和入度。但是,在邻接表中,不方 便获取顶点的入度。如果用邻接表的方式,又能达到比较方便获取每个顶点的出度和 入度。我们采用十字链表的存储方式,来实现图的存储。十字链表就是图的邻接表和 图的逆邻接表的结合。
邻接表需要一个一维数组来保存顶点。构建十字链表时,通过采用顶点节点和边节点, 来创建一个十字链表。
毕。
步骤3:
若此时图中尚有顶点未被访问,则我们再重 新选择一个未被访问的顶点作为初始顶点, 继续步骤2。若此时图中所有顶点皆被访问, 则算法结束。
8.3.1 深度优先遍历
31
图的深度优先遍历需要用一个栈来存放顶点,这主要是用了栈先进后出的特性。
下面对所示无向图进行深度优先遍历。
图8-29 无向图Baidu Nhomakorabea
8.3.1 深度优先遍历
互为邻接点;同时称边(vi,vj)依附于顶点vi和顶点vj。
有向图中,对于任意两个顶点vi和vj,若存在弧<vi,vj>,则称顶点vi邻接到 顶点vj,顶点vj邻接自顶点vi;同时称弧<vi, vj>依附于顶点vi和顶点vj。
图8-5 无向图
图8-6 有向图
8.1.2 图的基本用语(顶点的度、入度、出度)