1.23k likes | 1.35k Views
第 7 章 图. 知 识 点 图的逻辑结构特征及图的基本术语 邻接矩阵和邻接表两种图的存储结构的特点及适用范围 深度优先搜索和广度优先搜索两种遍历算法的特点和执行过程 生成树和最小生成树的概念及构造最小生成树的 prim 和 kruskal 算法 最短路径的含义及求最短路径的算法 拓扑排序的基本思想和步骤 关键路径法及其在管理科学中的作用. 难 点 图的遍历、最小生成树、最短路径、拓朴排序算法的理解 关键路径法求关键活动和关键路径的方法 要 求 熟练掌握以下内容: 图的存储结构 图的遍历算法 了解以下内容:
E N D
知 识 点 • 图的逻辑结构特征及图的基本术语 • 邻接矩阵和邻接表两种图的存储结构的特点及适用范围 • 深度优先搜索和广度优先搜索两种遍历算法的特点和执行过程 • 生成树和最小生成树的概念及构造最小生成树的prim和kruskal算法 • 最短路径的含义及求最短路径的算法 • 拓扑排序的基本思想和步骤 • 关键路径法及其在管理科学中的作用
难 点 • 图的遍历、最小生成树、最短路径、拓朴排序算法的理解 • 关键路径法求关键活动和关键路径的方法 • 要 求 熟练掌握以下内容: • 图的存储结构 • 图的遍历算法 了解以下内容: • 图的最小生成树和求最小生成树算法的基本思想 • 带权有向图的最短路径问题 • 利用AOV网络的拓朴排序问题 • 利用AOE网络的关键路径法
7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的连通性问题 7.5 有向无环图及其应用 7.6 最短路径
图的结构定义: 图是由一个顶点集 V 和一个弧集V R构成的数据结构。 Graph = (V, VR ) 其中,VR={<v,w>| v,w∈V 且 P(v,w)} <v,w>表示从 v 到 w 的一条弧,并称 v 为弧尾,w 为弧头。 谓词 P(v,w) 定义了弧 <v,w>的意义或信息。
A B E C D 由于“弧”是有方向的,因此称由顶点集和弧集构成的图为有向图。 例如: G1 = (V1, VR1) 其中 V1={A, B, C, D, E} VR1={<A,B>, <A,E>, <B,C>, <C,D>, <D,B>, <D,A>, <E,C> }
B C A D F E 若<v, w>VR必有<w, v>VR, 则称 (v,w) 为顶点 v 和顶点 w 之间存在一条边。 由顶点集和边集构成的图称作无向图。 例如: G2=(V2,VR2) V2={A, B, C, D, E, F} VR2={(A, B), (A, E), (B, E), (C, D), (D, F), (B, F), (C, F) }
名词和术语 网、子图 完全图、稀疏图、稠密图 邻接点、度、入度、出度 路径、路径长度、简单路径、简单回路 连通图、连通分量、 强连通图、强连通分量 生成树、生成森林
A B E C F A B E C A 弧或边带权的图分别称作有向网或无向网。 9 15 11 7 21 3 2 B 设图G=(V,{VR}) 和图G=(V,{VR}), 且VV, VRVR, 则称G 为 G 的子图。
假设图中有n个顶点,e条边,则 含有 e=n(n-1)/2 条边的无向图称作完全图; 含有 e=n(n-1) 条弧的有向图称作有向完全图; 若边或弧的个数 e<nlogn,则称作稀疏图,否则称作稠密图。
B C D A E F 假若顶点v 和顶点w 之间存在一条边, 则称顶点v和w互为邻接点, 边(v,w)和顶点v 和w相关联。 和顶点v 关联的边的数目定义为v的度。 例如: 右侧图中 TD(B) = 3 TD(A) = 2
对有向图来说, A B E C F 由于弧有方向性,则有入度和出度之分 顶点的出度: 以顶点v 为弧尾的弧的数目; 顶点的入度: 以顶点v为弧头的弧的数目。 例如: OD(B) = 1 顶点的度(TD)= 出度(OD)+入度(ID) ID(B) = 2 TD(B) = 3
A B E C F 设图G=(V,{VR})中的一个顶点序列 { u=vi,0,vi,1, …, vi,m=w}中,(vi,j-1,vi,j)VR 1≤j≤m, 则称从顶点u 到顶点w 之间存在一条路径。 路径上边的数目称作路径长度。 如:从A到F长度为 3 的路径{A,B,C,F} 简单路径:指序列中顶点不重复出现的路径。 简单回路:指序列中第一个顶点和最后一个顶点相同的路径。
C B D A E F C B D A E F 若图G中任意两个顶点之间都有路径相通,则称此图为连通图; 若无向图为非连通图,则图中各个极大连通子图称作此图的连通分量。
A A B E B E C F C F 对有向图, 若任意两个顶点之间都存在一条有向路径,则称此有向图为强连通图。 否则,其极大强连通子图称作它的强连通分量。
C B D A E F 假设一个连通图有 n 个顶点和 e 条边,其中 n-1 条边和 n 个顶点构成一个极小连通子图,称该极小连通子图为此连通图的生成树。 对非连通图,则称由各个连通分量的生成树的集合为此非连通图的生成森林。
C B D A E F 7.2 图的存储结构 一、图的数组(邻接矩阵)存储表示 二、图的邻接表存储表示 三、有向图的十字链表存储表示 四、无向图的邻接多重表存储表示
一、图的数组(邻接矩阵)存储表示 • 邻接矩阵是表示顶点之间相邻关系的矩阵。所谓两顶点的相邻关系即它们之间有边相连。 • 邻接矩阵是一个(n×n)阶方阵,n为图的顶点数,它的每一行分别对应图的各个顶点,它的每一列也分别对应图的各个顶点。我们规定矩阵的元素为:
0 (i,j)VR Aij={ 1 (i,j)VR B C A D F E 一、图的数组(邻接矩阵)存储表示 定义:矩阵的元素为 A B C D E F A B C D E F 1
A B E C F 有向图的邻接矩阵为非对称矩阵 0 1 0 1 00 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 1 0 0 0
图的邻接矩阵存储表示 #define INFINITY INT_MAX //最大值∞ #define MAX_CERTEX_NUM 20 //最大顶点数 typedef enum{DG,DN,UDG,UDN} GraphKind; //{有向图,有向网,无向图,无向网}
typedef struct ArcCell { // 弧的定义 VRType adj; // VRType是顶点关系类型。 // 对无权图,用1或0表示相邻否; // 对带权图,则为权值类型。 InfoType *info; // 该弧相关信息的指针 } ArcCell, AdjMatrix[MAX_VERTEX_NUM] [MAX_VERTEX_NUM];
typedef struct { // 图的定义 VertexType // 顶点信息 vexs[MAX_VERTEX_NUM]; AdjMatrix arcs; // 弧的信息 int vexnum, arcnum; // 顶点数,弧数 GraphKind kind; // 图的种类标志 } MGraph;
邻接矩阵表示法的特点 1.存储空间 • 无向图的邻接矩阵是对称的,如果A[i,j]=1,必有A[j,i]=1。这说明,只输入和存储其上三角阵元素即可得到整个邻接矩阵。其存储空间仅需n(n-1)/2 • 一般有向图的邻接矩阵是不对称的,A[i,j]不一定等于A[j,i]。其存储空间需n2 • 对于稀疏图而言,不适于用邻接矩阵来存储,因为这样会造成存储空间的浪费。
邻接矩阵表示法的特点 2.便于运算 • 便于判断判断图中任意两顶点是否有边(或弧)相连.即A[i,j]的值是0还是1 • 便于求得各顶点的度 无向图:其邻接矩阵第i行1的个数的和就是图中第i个顶点的度.即 有向图:第i行1的个数的和是第i个顶点的出度 第i列1的个数的和是第i个顶点的入度
邻接矩阵表示法的特点 3.便于实现图的一些基本操作 如:FirstAdjVertex(G,v): • 首先,由LocateVertex(G,v)找到v在图中的位置,即v在一维数组vexs中的序号I。 • 二维数组arcs中第i行上第一个adj域非零的分量所在的列号j,便是v的第一个邻接点在图G中的位置。 • 取出一维数组vexs[j]中的数据信息,即与顶点v邻接的第一个邻接点的信息。
二、图的邻接表存储表示 基本思想 • 邻接表是图的一种链接存储结构。 • 对于图中存在的边信息则存储起来,而对于不相邻接的顶点则不保留信息。在邻接表中,对图中的每个顶点建立一个带头结点的单链表,如第i个单链表中的结点则表示依附于顶点vi的边(若是有向图,则表示以vi为弧尾的弧)。每个单链表的头结点又构成一个表头结点表。
结构组成 一个n个顶点的图的邻接表表示需要有两部分构成: ①表头结点表 由所有表头结点以顺序结构(向量)的形式存储,以便可以随机访问任一顶点的单链表 ②表示图中顶点间邻接关系的n个单链表 (即边表或弧表)
adjvex nextarc info 弧结点的结构 typedef struct ArcNode { int adjvex; // 该弧所指向的顶点的位置 struct ArcNode *nextarc; // 指向下一条弧的指针 InfoType *info; // 该弧相关信息的指针 } ArcNode;
data firstarc 表头结点的结构 typedef struct VNode { VertexType data; // 顶点信息 ArcNode *firstarc; // 指向第一条依附该顶点的弧 } VNode, AdjList[MAX_VERTEX_NUM];
图的结构定义(邻接表) typedef struct { AdjList vertices; int vexnum, arcnum; int kind; // 图的种类标志 } ALGraph;
示例 B C A D A 1 4 B 0 4 5 C 3 5 D 2 5 E 0 1 F 1 2 3 0 1 2 3 4 5 F E
A B E A B C F E 0 1 2 3 4 1 4 C F 2 3 0 1 2 有向图的邻接表 可见,在有向图的邻接表中不易找到指向该顶点的弧
存储空间 • 对于有n个顶点,e条边的无向图而言,若采取邻接表作为存储结构,则需要n个表头结点和2e个表结点。很显然在边很稀疏(即e远小于n(n-1)/2时)的情况下,用邻接表存储所需的空间要比邻接矩阵所需的n(n-1)/2要节省得多。 • 在有向图邻接表中,一条弧对应一个表结点,表结点的数目和弧的数目相同。
无向图的度 • 在无向图的邻接表中,各顶点对应的单链表的结点数(不算表头结点)就等于该顶点的度数。
有向图的度 • 在有向图邻接表中,单链表的结点数就等于相应顶点的出度数。 • 要求有向图中某顶点的入度数,需扫视邻接表的所有单链表,统计与顶点标号相应的结点个数。 解决方法:再建立一个逆邻接表
A B E C D A B C D E 3 0 1 2 3 4 3 0 4 2 0 有向图的逆邻接表 在有向图的邻接表中,对每个顶点,链接的是指向该顶点的弧 1 ^
三、有向图的十字链表存储表示 十字链表(Orthogonal List)是有向图的另一种链式存储结构。我们也可以把它看成是将有向图的邻接表和逆邻接表结合起来形成的一种链表。有向图中的每一条弧对应十字链表中的一个弧结点,同时有向图中的每个顶点在十字链表中对应有一个结点,叫做顶点结点。
弧尾顶点位置 弧头顶点位置 弧的相关信息 弧的结点结构 tailvex headvex hlink tlink info 指向下一个有相同弧头的结点 指向下一个有相同弧尾的结点 typedef struct ArcBox { // 弧的结构表示 int tailvex, headvex; InfoType *info; struct ArcBox *hlink, *tlink; } VexNode;
顶点信息数据 顶点的结点结构 data firstin firstout 指向该顶点的第一条入弧 指向该顶点的第一条出弧 typedef struct VexNode { // 顶点的结构表示 VertexType data; ArcBox *firstin, *firstout; } VexNode;
有向图的结构表示(十字链表) typedef struct { VexNode xlist[MAX_VERTEX_NUM]; // 顶点结点(表头向量) int vexnum, arcnum; //有向图的当前顶点数和弧数 } OLGraph;
A C B 0 1 2 0 ∧ ∧ A B C 2 1 ∧ 0 2 ∧ ∧ 示例 0 1 2 ∧
深度优先搜索 广度优先搜索
一、深度优先搜索遍历图 连通图的深度优先搜索遍历 从图中某个顶点V0出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到。
V1 V2 V3 V5 V4 V7 V6 V8 深度优先遍历序列: v1 v2 v4 v8 v5 v3 v6 v7
从上页的图解可见: 1. 从深度优先搜索遍历连通图的过程类似于树的先根遍历; 2. 如何判别V的邻接点是否被访问? 解决的办法是:为每个顶点设立一个 “访问标志 visited[w]”;