数据结构(C语言版)_第7章 图及其应用

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(1)创建有向图邻接表 (2)创建无向图的邻接表
实现代码详见教材P208
7.4 图的遍历
图的遍历是对具有图状结构的数据线性化的过程。从图中任 一顶点出发,访问输出图中各个顶点,并且使每个顶点仅被访 问一次,这样得到顶点的一个线性序列,这一过程叫做图的遍 历。
图的遍历是个很重要的算法,图的连通性和拓扑排序等算法 都是以图的遍历算法为基础的。
V1
V1
V2
V3
V2
V3
V4
V4
V5
图9.1(a)

图7-2 图的逻辑结构示意图
7.2.2 图的相关术语
1.有向图与无向图 2.完全图 (1)有向完全图 (2)无向完全图 3.顶点的度 4.路径、路径长度、回路、简单路径 5.子图 6.连通、连通图、连通分量 7.边的权和网 8.生成树
2. while(U≠V) { (u,v)=min(wuv;u∈U,v∈V-U); U=U+{v}; T=T+{(u,v)}; }
3.结束
7.5.1 普里姆(prim)算法
【例7-10】采用Prim方法从顶点v1出发构造图7-11中网所对 应的最小生成树。
构造过程如图7-12所示。
16
V1
V1
V2
7.4.2 广度优先遍历
【例7-9】对于图7-10所示的有向图G4,写出从顶点A出发 进行广度优先遍历的过程。
访问过程如下:首先访问起始顶点A,再访问与A相邻的未被 访问过的顶点E、F,再依次访问与E、F相邻未被访问过的顶 点D、C,最后访问与D相邻的未被访问过的顶点B。由此得到 的搜索序列AEFDCB。此时所有顶点均已访问过, 遍历过程结束。
【例7-1】有向图G1的逻辑结构为:G1=(V1,E1) V1={v1,v2,v3,v4},E1={<v1,v2>,<v2,v3>,<v2,v4>,<v3,v4>,<v4,v1>,<v4,v3>}
【例7-2】无向图G2的逻辑结构为:G2=<V2,E2> V2={v1,v2,v3,v4,v5},E2={(v1,v2),(v1,v3),(v1,v4),(v2,v4),(v2,v5),(v3,v5),( v4,v5)} 常用类似图7-2(a)、7-2(b)的形式直观地表示图的逻辑结构。
7.3.2 邻接表
2.邻接链表特点 (1)若无向图G中有n个顶点,e条边,则它的邻接表需n个首结点存储单元
和2e个表结点。有向图存储n个顶点、e条边,需要n个存储单元和e个表结点。 在边稀疏的情况下(e<<n(n-1)/2),用邻接表表示图比用邻接矩阵节省存储 空间。
(2)一个图的邻接矩阵表示是唯一的,但其邻接链表表示是不唯一的。这 是因为邻接链表表示中,各个表结点的链接次序取决于建立邻接链表的算法 和输入次序。
7.4.1 深度优先遍历
【例7-8】有向图G5如图7-10所示,写出从顶点A出发按深 度优先遍历算法的顶点访问序列。
访问过程如下:在访问起始顶点A后,选择邻接点E,由于E 未曾访问过,则从E出发继续搜索;依次访问C、F。在访问了 C、F后,由于与F、C相邻的顶点均已访问,则搜索回到E。 继续访问与E相邻的未被访问的顶点D,依次类推,最后访问B。 由此得到的顶点访问序列是:AECFDB。此时所有 顶点均已访问过,遍历过程结束。
7.3.1 邻接矩阵
5.建立无向图的邻接矩阵的算法 (1)输入图的顶点数和边数。 (2)输入顶点的字符信息,建立顶点数组。 (3)初始化邻接矩阵。 (4)输入边的信息,建立图的邻接矩阵。
7.3.2 邻接表
1.邻接表的定义及其表示形式 对于图G,使用链表结构存储边的信息,链表的结构是对于每 一个顶点vi,将与其相邻的所有顶点链接成一个单链表,这个单链 表就称为顶点vi的邻接链表,单链表的结点形式如图7-8(b)所示。 另外使用一个一维数组来存储顶点的信息,数组元素的结构如 图7-8(a)所示。
下面分别介绍图的两种遍历方法:深度优先搜索和广度优先 搜索,这两种方法既适用于无向图也适用于有向图。
7.4.1 深度优先遍历
1.深度优先遍历的基本思想 深度优先遍历的思想类似于树的先序遍历,简称为DFS (Depth-First-Search)。其遍历过程基本思路如下:初始时 将图中的所有顶点标记为未被访问,从图中任选一个顶点vi出 发,访问该顶点并标记为已访问,然后访问任一个与vi邻接且 未被访问的邻接点vj,并标记vj为已访问,再从vj出发继续深 度优先遍历图中的其余顶点,重复这一过程,若到达某顶点不 存在未被访问过的邻接顶点时,则一直退回到最近被访问过的 且存在未被访问过的邻接顶点的那个顶点再进行深度优先遍历, 直至图中所有与vi有路径相通的顶点都被访问完为止。若此时 图中仍有未被访问的顶点,则另外选择一个未被访问的顶点, 从它出发,再进行深度优先遍历。直到图中的所有顶点都被访 问为止。可以看出,深度优先遍历是一个递归的过程,其特点 是尽可能地向纵深方向进行搜索。
图7-1 6个城镇的公路交通图
思考:1.如何保证光缆线路通畅。 2.如何节省成本。
7.2 图的概念和术语
7.2.1 图的定义及其逻辑结构。
图是由结点的有穷集合V和边的集合E组成,可形式化定义为G=(V,E)
其中 V={vi|vi∈dataobject} E={<vi,vj>或(vi,vj)|vi,vj∈V且P(vi,vj)}
16
V1
V2
5
6
V3
V4
16
V1
V2
V6 11 6
5
V3
V4
16
V1
V2
5
V3
16
V1
V2
V6 11 6
5
V3
18
V5
V4
图7-12 Prim法构造最小生成树的过程示意图
7.5.2 克鲁斯卡尔(kruskal)算法
克鲁斯卡尔(kruskal)算法的基本思想为:为使生成树上 总的权值之和达到最小,应使每一条边上面的权值尽可能小, 所以应从权值最小的边选起,直至选出n-1条权值最小的边为 止,这n-1条边必须不构成回路。因此并非每一条当前权值最 小的边都可选。
vertex firstedge
adjvex next
(a)邻接表的表头数组元素结构 (b)邻接表的结点结构
图7-8 邻接表结点的形式
7.3.2 邻接表
【例7-7】画出图7-2中有向图G1和无向图G2对应的邻接表。 分析:根据邻接表的定义,画出邻接表如图7-9所示。
(a)有向图G1的邻接表表示形式 (b)无向图G2的邻接表表示形式 图7-9 图7-2中有向图G1与无向图G2的邻接表表示形式
7.5 最小生成树
对于有n个顶点的无向连通图,无论其生成树的形态如何, 所有生成树中都有且仅有n-1条边。对于无向连通网,它的所 有生成树中必有一棵边的权值总和最小的生成树,我们称这棵 生成树为最小生成树,
关于最小生成树的实际应用,在本章开始图的引例中已经给 出其具体应用,即在n个城市之间建立通信网络并使总造价最 低。
具体做法如下:设G=(V,E)是一个无向连通网。设置两 个新的集合U和T,其中集合U存放G中最小生成树的顶点,集 合T存放G的最小生成树的边。
1.初始时将所有G的顶点ui都放在U中来构造最小生成树, 故令U的初值为{u1,u2,……,un},T的初值为空。
2.把G的边按照权值升序排列。 3.从G的边中选择一条权值最小的边(u,v)加入到T中。 4.重复3过程,直到G中所有顶点都在同一个连通分量时为 止。最小生成树构造完毕。
多数算法利用了最小生成树的下述性质: 设G=(V, E)是一个连通图,在E上定义一个权函数,U是 顶点集V的一个非空子集,如果(u, v)是一条具有最小权 值的边,其中u∈U,v∈V-U,则必存在一棵包含边(u, v) 的最小生成树。
7.5.1 普里姆(prim)算法
Prim算法的基本思想:设G=(V,E)是一个无向连通网。设置两个新的 集合U和T,其中集合U存放G中最小生成树的顶点,集合T存放G的最小生成 树的边。
1.假设从图G的顶点u1开始构造最小生成树,故令U的初值为{u1},T的初 值为空。
2.从所有顶点满足u∈U,v∈V-U的边中,选取一条权值最小的边(u,v), 将顶点v加入到U中,边(u,v)加入到T中。
3. 重复2过程,直到U=V时为止。最小生成树构造完毕。
该过程用形式化语言可描述为:
1.U={u1},T={};
7.2.3 图的基本操作
1.创建一个图结构 CreateGraph(G)。 2.深度优先遍历图 DFSTraverse(G,v)。 3.广度优先遍历图 BFSTraverse(G,v)。 4.顶点定位 LocateVex(G,v)。 5.求图中第i个顶点 GetVex(G,i)。 6.求第一个邻接点FirstAdjVex(G,v)。 7.求下一个邻接点NextAdjVex(G,v,w)。
第七章 图及其应用
本章要点
➢图的定义、相关术语及图的逻辑结构。 ➢图的存储结构。 ➢图的遍历方法。 ➢最小生成树。 ➢最短路径。 ➢拓扑排序。
7.1 “最小代价通信网”案例导入
“最小代价通信网”引例:已知存在6个城镇,用 v1,v2,v3,v4,v5,v6表示,连接6个城镇的公路交通图如图7-1所示。 现要求沿公路架设6个城镇的光缆线,以满足通信要求,即任意两 个城镇之间都有直接或者间接的通信线路,已知每两个城镇之间的 通信线路的造价(图7-1中边上的数值表示造价),请设计出通信网 络方案,满足总造价最低。
B
C
E D
F A
图7-10 有向图G5
7.4.2 广度优先遍历
1.广度优先遍历的基本思想 广度优先遍历方法类似于树的层次遍历,简记为BFS (Breadth-First-Search)。其基本思想是:初始时将图中所 有顶点标记为未被访问过,从图中任一个顶点v出发,在访问 该顶点v之后,依次访问v的所有未被访问过的邻接点,并标记 为已访问,然后再访问每个邻接点的邻接点,且访问顺序应保 持先被访问的顶点其邻接点也优先被访问,直至图中所有已被 访问的顶点的邻接顶点都被访问到。若此时图中仍有未被访问 的顶点,则另选一个未被访问的顶点,开始再做广度优先搜索, 直到图中的所有顶点都被访问为止。可以看出,广度优先搜索 也是个递归的过程。
(3)无向图中,第i个链表中的表结点数是顶点vi的度,有向图中,第i个 链表中的表结点是顶点vi的出度。
(4)在邻接链表中,要确定两个顶点vi和vj之间是否有边或弧相连,需要 遍历第i个或第j个单链表,不像邻接矩阵那样能方便的对顶点进行随机访问。
7.3.2 邻接表
3.创建有向图和无向图邻接表的算法实现
7.3.1 邻接矩阵
3.网的邻接矩阵
1.有向网的邻接矩阵 2.无向网的邻接矩阵 【例7-6】画出如图7-4所示的无向网G3顶点相邻关系的邻接矩阵。
图7-7 图7-4所示网的邻接矩阵
7.3.1 邻接矩阵
4.图的邻接矩阵存储方法的特点 1)无向图的邻接矩阵一定是对称的,而有向图的邻接矩阵则不一 定对称。因此,用邻接矩阵来表示一个具有n个顶点的有向图时需 要n2个存储单元来存储;而对于具有n个顶点的无向图则只需存入 其上(下)三角形,故只需n(n+1)/2个存储单元来存储。邻接矩阵 表示法的空间复杂度为O(n2)。 2)用邻接矩阵方法存储图,很容易确定图中任意两个顶点之间是 否有边相连。但是,如果要确定图中有多少条边,则必须按照行、 列对每个元素进行检查,所花费的时间代价很大,这是用邻接矩阵 存储图的局限性。
7.3 图的存储结构
7.3.1 邻接矩阵
1.有向图的邻接矩阵
假设该矩阵的名称为M,则当<vi,vj>是该有向图中的一条弧时,M[i][j]=1;否则
M[i][j]=0。
2.无向图的邻接矩阵
假设该矩阵的名称为M,则当(vi,vj)是该无向图中的一条边时,M[i][j]= M[j][i]=1; 否则,M[i][j]= M[j][i]=0。由于在任何情况下,M[i][j]和M[i][j]都相等,所以无向图 的邻接矩阵必然是对称矩阵。
•【例7-5】画出如图7-2所示的有向图G1和无向图G2表示顶点相邻关系的邻接矩阵
V1
V2
V3
V4
V5
01110 10011 M= 1 0 0 0 1 11001 01110
V1
V2
V4
V5
图7-6
01110
10011
V3
M= 1 0 0 0 1
11001
01110
图7-2所示的G1与G2与相应的邻接矩阵
相关文档
最新文档