1 / 97

第七章 图

第七章 图. 7.1 图的定义和术语. 7.2 图的存储结构. 7.3 图的遍历. 7.4 最小生成树. 7.5 拓扑排序. 7.6 关键路径. 7.7 最短路径. 7.1 图的定义和术语. 图定义 图是由顶点集合 (vertex) 及顶点间的关系集合组成的一种数据结构: Graph = ( V, E ) 其中 V = { x | x  某个数据对象 } 是顶点的有穷非空集合; E1 = {(x, y) | x, y  V }

winka
Download Presentation

第七章 图

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第七章 图

  2. 7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 最小生成树 7.5 拓扑排序 7.6 关键路径 7.7 最短路径

  3. 7.1 图的定义和术语 图定义 图是由顶点集合(vertex)及顶点间的关系集合组成的一种数据结构: Graph=( V, E ) 其中 V = { x | x 某个数据对象} 是顶点的有穷非空集合; E1 = {(x, y) | x, y  V } 或 E2 = {<x, y> | x, y  V && Path (x, y)} 其中, E1是顶点之间关系的有穷集合,也叫做边(edge)集合,此时的图称为无向图。 E2 表示从 x 到 y 的一条弧,且称x为弧尾,y为弧头,这样的图称为有向图。

  4. V2 V1 V3 V5 V4 V1 V2 V4 V3 若顶点vi和vj之间的边没有方向,则称这条边为无向边,表示为(vi,vj)。 如果图的任意两个顶点之间的边都是无向边,则称该图为无向图。 若从顶点vi到vj的边有方向,则称这条边为有向边,表示为<vi,vj>。 如果图的任意两个顶点之间的边都是有向边,则称该图为有向图。

  5. 图的基本术语 完全图若有 n 个顶点的无向图有 n(n-1)/2条边, 则此图为无向完全图。有 n 个顶点的有向图有n(n-1)条边, 则此图为有向完全图。 0 0 0 0 1 1 2 1 2 1 3 3 4 5 6 2 2

  6. 0 0 0 0 子图 1 2 1 1 2 2 3 3 3 3 • 邻接顶点如果 (u, v) 是 E(G) 中的一条边,则称 u 与 v 互为邻接顶点。 • 子图设有两个图 G=(V, E) 和 G‘=(V’, E‘)。若 V’ V 且 E‘E, 则称 图G’ 是 图G 的子图。 • 权某些图的边具有与它相关的数, 称之为权。这种带权图叫做网络。

  7. 顶点的度一个顶点v的度是与它相关联的边的条数。记作TD(v)。在有向图中, 顶点的度等于该顶点的入度与出度之和。 • 顶点 v 的入度是以 v 为终点的有向边的条数, 记作 ID(v); 顶点 v 的出度是以 v 为始点的有向边的条数, 记作 OD(v)。 • 路径 在图 G=(V, E) 中, 若从顶点 vi 出发, 沿一些边经过一些顶点 vp1, vp2, …, vpm,到达顶点vj。则称顶点序列 (vi vp1 vp2 ... vpm vj) 为从顶点vi到顶点 vj的路径。它经过的边(vi, vp1)、(vp1, vp2)、...、(vpm, vj) 应是属于E的边。

  8. A B E C F 有向图 顶点的出度: 以顶点v 为弧尾的弧的数目; 顶点的入度: 以顶点v为弧头的弧的数目。 例如: 顶点的度(TD)=出度(OD)+入度(ID) TD(B) =OD(B)+2ID(B) = 3

  9. 路径长度非带权图的路径长度是指此路径上边的条数。带权图的路径长度是指路径上各边的权之和。路径长度非带权图的路径长度是指此路径上边的条数。带权图的路径长度是指路径上各边的权之和。 • 简单路径若路径上各顶点 v1,v2,...,vm 均不 互相重复, 则称这样的路径为简单路径。 • 简单回路 若路径上第一个顶点 v1 与最后一个顶点vm 重合, 则称这样的路径为回路或环。 0 0 0 1 2 1 2 1 2 3 3 3

  10. A B E C F 如:从A到F长度为 3 的路径{A,B,C,F}

  11. 连通图与连通分量在无向图中, 若从顶点v1到顶点v2有路径, 则称顶点v1与v2是连通的。如果图中任意一对顶点都是连通的, 则称此图是连通图。非连通图的极大连通子图叫做连通分量。 • 强连通图与强连通分量在有向图中, 若对于每一对顶点vi和vj, 都存在一条从vi到vj和从vj到vi的路径, 则称此图是强连通图。非强连通图的极大强连通子图叫做强连通分量。

  12. C B D A E F C B D A E F 无向图,若图中任意两个顶点之间都有路径相通,则称此图为连通图; 若无向图为非连通图,则图中各个极大连通子图称作此图的连通分量。

  13. A B E C F 有向图,若任意两个顶点之间都存在一条有向路径,则称此有向图为强连通图。 否则,其各个强连通子图称作它的强连通分量。 A B E C F

  14. C B D A E F 生成树:假设一个连通图有 n 个顶点和 e 条边,其中 n-1 条边和 n 个顶点构成一个极小连通子图,称该极小连通子图为此连通图的生成树。在极小连通子图中增加一条边,则一定有环。 在极小连通子图中去掉一条边,则成为非连通图。 C B D A E F

  15. A D C B A F B C E D F E 有n个顶点,n-1条边的图必定是生成树吗? 对非连通图,则称由各个连通分量的生成树的集合为此非连通图的生成森林。

  16. 7.2 图的存储结构 一、图的数组(邻接矩阵)存储表示 二、图的邻接表存储表示 三、有向图的十字链表存储表示 四、无向图的邻接多重表存储表示

  17. 一、图的数组(邻接矩阵)存储表示 0 (i,j)VR Aij={ 定义:矩阵的元素为 1 (i,j)VR A B C D E F B C A B C D E F A D F E 无向图的邻接矩阵为对称矩阵

  18. A B C D E A B C D E A B D C E 有向图的邻接矩阵为非对称矩阵

  19. 邻接矩阵表示法特点: 1)无向图邻接矩阵是对称矩阵,同一条边表示了两次; 2)顶点v的度:在无向图中等于二维数组对应行(或列) 中1的个数;在有向图中, 统计第 i 行 1 的个数可得 顶点 i 的出度,统计第 j 列 1 的个数可得顶点 j 的 入度。 3)判断两顶点v、u是否为邻接点:只需判二维数组对应 分量是否为1; 4)顶点不变,在图中增加、删除边:只需对二维数组对 应分量赋值1或清0; 5)设存储顶点的一维数组大小为n(图的顶点数n), G占 用存储空间:n+n2;G占用存储空间只与它的顶点数有关 ,与边数无关;适用于边稠密的图;

  20. typedef struct ArcCell { // 弧的定义 VRType adj; // VRType是顶点关系类型// 对无权图,用1或0表示相邻否; // 对带权图,则为权值类型。 InfoType *info; // 该弧相关信息的指针 } ArcCell, AdjMatrix[MAX_VERTEX_NUM] [MAX_VERTEX_NUM];

  21. typedef struct { // 图的定义 VertexType // 顶点信息 vexs[MAX_VERTEX_NUM]; AdjMatrix arcs; // 弧的信息 int vexnum, arcnum; // 顶点数,弧数 GraphKind kind; // 图的种类标志 } MGraph;

  22. 网络的邻接矩阵 A 9 15 11 B D 7 21 3 C E 2

  23. 二、图的邻接表 存储表示 B C A D 0 A 1 4 1 B 0 4 5 2 C 3 5 3 D 2 5 4 E 0 1 5 F 1 2 3 F E 同一个顶点发出的边 链接在同一个边链表中 ,每一个链结点代表一 条边(边结点), 结点中有 另一顶点的下标 adjvex 和指针 nextedge。

  24. 有向图的邻接表 A 0 1 2 3 4 A B C D E  1 4 B E  2  C D 3  0 1 可见,在有向图的邻接表中不易找到指向该顶点的弧。  2

  25. A 有向图的逆邻接表 B E 在有向图的邻接表中,对每个顶点,链接的是指向该顶点的弧。 C D A B C D E 3  0 1 2 3 4 3 0  4  2  0 

  26. 邻接表表示法特点: 1)无向图邻接表边结点数是边数的两倍. 2)顶点vi的度:在无向图中等于第i个链表中的 结点数;在有向图邻接表中,第i行的结点数等于 顶点i的出度,在有向图逆邻接表中,第i行的结点 数等于顶点i的入度。 3)在邻接表上容易找到任一顶点的第一个邻接点 和下一个邻接点 4)设存储顶点的一维数组大小为n(图的顶点数n), G占用存储空间:n+e;G占用存储空间与它的顶 点数和边数有关;适用于边稀疏的图;

  27. 弧的结点结构 adjvex nextarc info typedef struct ArcNode { int adjvex; // 该弧所指向的顶点的位置 struct ArcNode *nextarc; // 指向下一条弧的指针 InfoType *info; // 该弧相关信息的指针 } ArcNode;

  28. 顶点的结点结构 data firstarc typedef struct VNode { VertexType data; // 顶点信息 ArcNode *firstarc; // 指向第一条依附该顶点的弧 } VNode, AdjList[MAX_VERTEX_NUM];

  29. 图的结构定义 typedef struct { AdjList vertices; int vexnum, arcnum; int kind; // 图的种类标志 } ALGraph;

  30. 三、有向图的十字链表存储表示 弧的结点结构 弧尾顶点位置 弧头顶点位置 弧的相关信息 指向下一个有相同弧尾的结点 指向下一个有相同弧头的结点 typedef struct ArcBox { // 弧的结构表示 int tailvex, headvex; InfoType *info; struct ArcBox *hlink, *tlink; } VexNode;

  31. 顶点的结点结构 顶点信息数据 指向该顶点的第一条入弧 指向该顶点的第一条出弧 typedef struct VexNode { // 顶点的结构表示 VertexType data; ArcBox *firstin, *firstout; } VexNode;

  32. 有向图的结构表示(十字链表) typedef struct { VexNode xlist[MAX_VERTEX_NUM]; // 顶点结点(表头向量) int vexnum, arcnum; //有向图的当前顶点数和弧数 } OLGraph;

  33. B A D C 0 1 2 3

  34. 四、无向图的邻接多重表存储表示 边的结构表示 typedef struct Ebox { VisitIf mark; // 访问标记 int ivex, jvex; //该边依附的两个顶点的位置 struct EBox *ilink, *jlink; InfoType *info; // 该边信息指针 } EBox;

  35. 顶点的结构表示 typedef struct VexBox { VertexType data; EBox *firstedge; // 指向第一条依附该顶点的边 } VexBox; 无向图的结构表示 typedef struct { // 邻接多重表 VexBox adjmulist[MAX_VERTEX_NUM]; int vexnum, edgenum; } AMLGraph;

  36. B A C D E 0 1 2 3 4

  37. 7.3 图的遍历 从图中某个顶点出发游历图,访遍 图中其余顶点,并且使图中的每个顶点 仅被访问一次的过程。 深度优先搜索 广度优先搜索 遍历应用举例

  38. 一、深度优先搜索遍历图 连通图的深度优先搜索遍历 从图中某个顶点V0 出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到。

  39. W1、W2和W3均为 V 的邻接点,SG1、SG2 和 SG3 分别为含顶点W1、W2和W3的子图。 V w1 w3 w2 w2 SG3 SG1 SG2 访问顶点 V : for (W1、W2、W3 ) 若该邻接点W未被访问, 则从它出发进行深度优先搜索遍历。

  40. 从上页的图解可见: 1. 从深度优先搜索遍历连通图的过程类似于树的先根遍历; 2. 如何判别V的邻接点是否被访问? 解决的办法是:为每个顶点设立一个 “访问标志 visited[w]”。

  41. 例如: 0 a a 2 3 4 5 c c d d e e f f b g g b 1 6 0 1 2 3 4 5 6 访问标志: F F F F F F F T T T T T T T 访问次序: a c b d g f e

  42. void DFS(Graph G, int v) { // 从顶点v出发,深度优先搜索遍历连通图 G visited[v] = TRUE; VisitFunc(v); for(w=FirstAdjVex(G, v); w!=0; w=NextAdjVex(G,v,w)) if (!visited[w]) DFS(G, w); // 对v的尚未访问的邻接顶点w // 递归调用DFS } // DFS

  43. 非连通图的深度优先搜索遍历 首先将图中每个顶点的访问标志设为 FALSE, 之后搜索图中每个顶点,如果未被访问,则以该顶点为起始点,进行深度优先搜索遍历,否则继续检查下一顶点。

  44. 例如: 0 1 6 a a b b g g 2 3 4 5 c c d d e e f f h h k k 7 8 0 1 2 3 4 5 6 7 8 访问标志: F F F F F F F F F T T T T T T T T T 访问次序: a c h d k f e b g

  45. void DFSTraverse(Graph G, Status (*Visit)(int v)) { // 对图 G 作深度优先遍历。 VisitFunc = Visit; for (v=0; v<G.vexnum; ++v) visited[v] = FALSE; // 访问标志数组初始化 for (v=0; v<G.vexnum; ++v) if (!visited[v]) DFS(G, v); // 对尚未访问的顶点调用DFS }

  46. 二、广度优先搜索遍历图 对连通图,从起始点V到其余各顶点必定存在路径。 w2 w2 w1 w1 其中,V->w1, V->w2, V->w8 的路径长度为1; V V w3 w3 w7 w7 V->w7, V->w3, V->w5 的路径长度为2; w8 w8 w4 w4 w6 w6 V->w6, V->w4 的路径长度为3。 w5 w5

  47. 从图中的某个顶点V0出发,并在访问此顶点之后依次访问V0的所有未被访问过的邻接点,之后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有和V0有路径相通的顶点都被访问到。从图中的某个顶点V0出发,并在访问此顶点之后依次访问V0的所有未被访问过的邻接点,之后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有和V0有路径相通的顶点都被访问到。 若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

  48. 0 1 2 3 4 5 6 7 8 T T T T T T T T T F F F F F F F F F Visited Q w2 w2 w1 V w2 w8 w7 w3 w5 w6 w4 w1 w1 V V w3 w3 访问次序: w7 w7 w8 w8 w4 w4 w6 w6 w5 w5

  49. void BFSTraverse(Graph G, Status (*Visit)(int v)){ for (v=0; v<G.vexnum; ++v) visited[v] = FALSE; //初始化访问标志 InitQueue(Q); // 置空的辅助队列Q for ( v=0; v<G.vexnum; ++v ) if (!visited[v]) { // v 尚未访问 } } // BFSTraverse

  50. visited[u] = TRUE; Visit(u); // 访问u EnQueue(Q, v);// v入队列 while (!QueueEmpty(Q)) { DeQueue(Q, u); // 队头元素出队并置为u for(w=FirstAdjVex(G, u); w!=0; w=NextAdjVex(G,u,w)) if ( ! visited[w]){ visited[w]=TRUE; Visit(w); EnQueue(Q, w);// 访问的顶点w入队列 } // if } // while

More Related