1.5k likes | 1.65k Views
第 7 章 图. 7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的连通性问题 7.5 有向无环图的应用 7.6 最短路径. 本章重点难点. 重点 : (1) 图的定义、术语和性质; (2)ADT 图的设计和实现; (3) 图的邻接矩阵、邻接表的存储结构及其构造方法; (4) 图的两种遍历方法:深度优先遍历和广度优先遍历; (5) 最小生成树的算法、拓扑排序的算法; (6) 理解关键路径的算法,构造最短路径的 Dijkstra 算法和 Floyed 算法。.
E N D
第7章 图 7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的连通性问题 7.5 有向无环图的应用 7.6 最短路径
本章重点难点 重点:(1)图的定义、术语和性质;(2)ADT图的设计和实现;(3)图的邻接矩阵、邻接表的存储结构及其构造方法;(4)图的两种遍历方法:深度优先遍历和广度优先遍历;(5)最小生成树的算法、拓扑排序的算法;(6)理解关键路径的算法,构造最短路径的Dijkstra算法和Floyed算法。 难点:有向无环图的关键路径算法,求最短路径的Dijkstra算法和Floyed算法。
第七章 图 7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的连通性问题 7.5 有向无环图的应用 7.6 最短路径
V0 V1 V2 V3 V4 G1图示 7.1 图的定义和术语 • 图的定义 图G由两个集合构成,记作G=<V,E> 其中V是顶点的非空有限集合,E是边的有限集合,其中边是顶点的无序对或有序对集合。 例 G1=<V1,E1> V1={v0 ,v1,v2,v3,v4 } E1={ (v0,v1),(v0,v3),(v1,v2), (v1,v4),(v2,v3)(v2,v4) }
7.1 图的定义和术语 • 图的术语 无向图(Undigraph) :在图G中,若所有边是无向边,则称G为无向图; 有向图(Digraph) :在图G中,若所有边是有向边,则称G为有向图;有向边也称为弧(Arc)。 V0 V1 V0 V1 V2 V3 V4 V3 V2 G1图示 有向图 无向图 G2 图示
7.1 图的定义和术语 • 图的术语 无向完全图(Undirected Complete Graph): 无向图且边数为n(n-1)/2,则称其为无向完全图; 有向完全图(Directed Complete Graph): 有向图且边数为n(n-1) ,则称其为有向完全图 邻接点及关联边 邻接点:边的两个顶点 关联边:若边e= (v, u), 则称顶点v、u 关连边e
7.1 图的定义和术语 • 图的术语 顶点的度: 一个顶点v的度是与它相关联的边的条数,记作D(v)。 顶点v的入度是以v为终点的有向边的条数, 记作ID(v); 顶点v的出度是以v为始点的有向边的条数,记作 OD(v)。 顶点数、边数e和度数D(v)之间的关系:
7.1 图的定义和术语 • 图的术语 路径、回路: 有向图D=(V,E)中的顶点序列v1,v2,… ,vk, 若<vi,vi+1>E (i=1,2,…k-1), v =v1, u =vk, 则称该序列是从顶点v到顶点u的路径;若v=u,则称该序列为回路; 路径、回路:无向图G=(V,E)中的顶点序列v1,v2,… ,vk,若(vi,vi+1)E( i=1,2,…k-1), v =v1, u =vk, 则称该序列是从顶点v到顶点u的路径;若v=u,则称该序列为回路;
7.1 图的定义和术语 例 在图1中,V0,V1,V2,V3 是V0到V3的路径;V0,V1,V2,V3,V0是回路; 在图2中,V0,V2,V3 是V0到V3的路径; V0,V2,V3,V0是回路; V0 V1 V0 V1 V2 V3 V4 V3 V2 无向图G1 有向图G2
7.1 图的定义和术语 • 图的术语 简单路径和简单回路: 在一条路径中,若除起点和终点外,所有顶点各不相同,则称该路径为简单路径;由简单路径组成的回路称为简单回路;
7.1 图的定义和术语 例 在图1中,V0,V1,V2,V3 是简单路径; V0,V1,V2,V4,V1不是简单路径。 在图2中, V0,V2,V3,V0是简单回路。 V0 V1 V0 V1 V2 V3 V4 V3 V2 无向图G1 有向图G2
7.1 图的定义和术语 • 图的术语 连通图(强连通图): 在无(有)向图G=< V, E >中,若对任何两个顶点 v、u 都存在从v 到 u 的路径,则称G是连通图(强连通图)
7.1 图的定义和术语 • 图的术语 子图: 设有两个图G=(V,E)、G1=(V1,E1),若V1 V,E1 E,E1关联的顶点都在V1中,则称 G1是G的子图; 权: 某些图的边具有与它相关的数, 称之为权。 这种带权图叫做网络。
7.1 图的定义和术语 • 图的术语 生成树:连通图的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G 的生成树。 T是G 的生成树当且仅当T 满足如下条件 T是G 的连通子图 T包含G 的所有顶点 T中无回路
7.1 图的定义和术语 • 图的抽象数据类型定义 ADT Graph { 数据对象V: 数据关系R: 基本操作 } ADT Graph V是具有相同特征的数据元素的 集合,称为顶点集。 R={VR} VR={<v,w>︱v,w∈V且P(v,w) 见下页
7.1 图的定义和术语 • 基本操作 CreatGraph(&G) //建立图 DestroyGraph(&G) //销毁图 InsertVEx(&G, v) //插入顶点 DeleteVEx(&G, v) //删除顶点 InsertArc(&G, v, w) //插入弧 DeleteArc(&G, v, w) //删除弧 DFSTraVErse(G, v, Visit()) //深度优先搜索 BFSTraVErse(G, v, Visit()) //广度优先搜索
第七章 图 7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的连通性问题 7.5 有向无环图的应用 7.6 最短路径
7.2 图的存储结构 7.2.1、数组表示法 7.2.2、邻接表
7.2 图的存储结构 图的存储结构至少要保存两类信息: (1)顶点的数据 (2)顶点间的关系 如何表示顶点间的关系? ? 约定: 图G=<V, E>, V={v0,v1,v2, … vn-1 },顶 点的角标为它的编号。
7.2.1 数组表示法 • 邻接矩阵 (Adjacency Matrix) G的邻接矩阵是满足如下条件的n阶矩阵: 1 若(vi,vi+1)E 或 <vi,vi+1>E 0 否则 A[i][j]=
7.2.1 数组表示法 例 无向图的邻接矩阵 0 1 2 3 0 0 1 1 1 1 1 0 0 1 2 1 0 0 1 3 1 1 1 0 V0 V1 V2 V3 讨论: (1)无向图中第i个顶点的度在邻接矩阵中如何体现? (2)图的总度数怎么求, (3)边数怎么求?
7.2.1 数组表示法 例 无向图的邻接矩阵 0 1 2 3 0 0 1 1 1 1 1 0 0 1 2 1 0 0 1 3 1 1 1 0 V0 V1 V2 V3 答案: (1)第i行(或第i列)的非零元素个数之和; (2)非零元个数之和; (3)边数为总度数的一半。
7.2.1 数组表示法 例 有向图的邻接矩阵 0 1 2 3 4 0 1 2 3 4 0 1 1 0 0 v0 v1 0 0 1 0 0 v4 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 v3 v2 讨论: 有向图中第i个顶点的出度和入度在邻接矩阵中如何体现? 边数是多少?
7.2.1 数组表示法 例 有向图的邻接矩阵 0 1 2 3 4 0 1 2 3 4 0 1 1 0 0 v0 v1 0 0 1 0 0 v4 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 v3 v2 答案: 第i行的非零元个数之和; 第i列的非零元个数之和; 边数为非零元的个数。
7.2.1 数组表示法 • 网络的邻接矩阵 网络的邻接矩阵是满足如下条件的n阶矩阵: Wij 若(vi,vi+1)E 或 <vi,vi+1>E 0 或 否则 A[i][j]=
7.2.1 数组表示法 例 边带权图(网)的邻接矩阵示例: 2 0 1 2 3 4 v0 v1 2 ∞ 2 ∞ ∞ ∞ 0 1 2 3 4 ∞ ∞ 4 ∞ ∞ 4 v4 ∞ ∞ ∞ 2 ∞ ∞ ∞ ∞ ∞ 2 2 ∞ ∞ ∞ ∞ 2 v3 v2 2 讨论:无穷大在实际应用中怎么表示? 答案:用一个足够大的数表示。
7.2.1 数组表示法 • 邻接矩阵的类型实现 #define INFINITY INT_MAX //最大值 #define MAX_VERTEX_NUM //最大顶点个数 Typedef enum {DG,DN,UDG,UDN} GraphKind; typedef struct ArcCell { // 弧的定义 VRType adj;// VRType是顶点关系类型 InfoType *info;// 该弧相关信息的指针 } ArcCell, AdjMatrix[MAX_VERTEX_NUM] [MAX_VERTEX_NUM];
7.2.1 数组表示法 • 图的类型实现 typedef struct { // 图的类型定义 VErtexType // 顶点信息 vexs[MAX_VERTEX_NUM]; AdjMatrix arcs;// 弧的信息 int vexnum, arcnum;// 顶点数,弧数 GraphKind kind;// 图的种类标志 } MGraph; MGraph G;
7.2.1 数组表示法 例 网的存储示例图 2 5 20 40 70 1 4 50 80 30 6 3
7.2.1 数组表示法 • 建立无向网络(边带权图)G的算法概要: 首先读入顶点数G.VExnum,边数G.arcnum,图的种类G.kind 1、给顶点域赋值:G.vexs[i]; 2、给边域赋值: ① 边域初始化:G.arcs[i][j].adj=INFINITY; ② 读入边及权重i,j,w, G.arcs[i][j].adj=W; G.arcs[j][i].adj=W。
7.2.1 数组表示法 • 建立无向网络(边带权图)G的算法详解: void Creatgraph(MGraph &G) {int i,j,k;float w; scanf(“%d,%d,%d”,G.VExnum,G.arcnum,G.kind); for(i=1;i<=G.VExnum;i++) G.VExs[i]=getchar(); 见下页
7.2.1 数组表示法 接上页 for(i=1;i<=G.VExnum;i++) for(j=1;j<=G.VExnum;j++) G.arcs[i][j].adj=INFINITY; G.arcs[i][j].info=NULL; for (k=1;k<=G.arcnum;k++) {scanf(“%d,%d,%f”,&i,&j,&w); G.arcs[i][j]=w; G.arcs[j][i]=w; } }
7.2.1 数组表示法 • 邻接矩阵的特点 (1)空间复杂度O(n2) (2)操作特点 边或弧的删除和插入操作容易。顶点的插入删除操作不容易。
7.2.2 邻接表 例 无向图的邻接表示例: V0 V1 顶点表 边表 V2 V3 0 1 2 3 4 讨论:如何求无向图邻接表中第i个顶点的度?图的总度数,边数?
7.2.2 邻接表 例 无向图的邻接表示例: V0 V1 V2 V3 讨论:如何求无向图邻接表中第i个顶点的度? 图的总度数? 边数? 答案:第i个顶点的边链表结点个数之和。 所有边链表结点个数之和。 所有边链表结点个数之和的一半。
7.2.2 邻接表 例 有向图的邻接表示例: v2 v1 出边表 顶点表 v3 v5 v4 讨论:求有向图邻接表中第i个顶点的出度?图的边数?
7.2.2 邻接表 例 有向图的邻接表示例: v2 v1 v3 v5 v4 讨论:求有向图邻接表中第i个顶点的出度?图的边数? 答案:第i个顶点的边链表结点个数之和。 所有边链表结点个数之和。
7.2.2 邻接表 • 邻接表的定义 边链表: 顶点表: 邻接表的定义分两部分: 边链表:与顶点V关联的所有边组成一个链表,称为顶点V的边链表。在边链表中,其结点结构如下: 表结点
7.2.2 邻接表 • 邻接表的定义 顶点表:用顺序存储方式存储图的顶点表v1,v2,v3,…vn,每个顶点的结构。 邻接表:由顺序存储的顶点表和链接存储的边链表构成的图的存储结构被称为邻接表。
7.2.2 邻接表 • 邻接表的存储实现 #define MAX_VERTEX_NUM 20 (1)边表的存储类型: typedef struct ArcNode { int adjvex; // 该弧所指向的顶点的位置 struct ArcNode *nextarc; // 指向下一条弧的指针 InfoType *info; // 该弧相关信息的指针 } ArcNode;
7.2.2 邻接表 • 邻接表的存储实现 (2)顶点表的存储类型: typedef struct vnode { vertextype data; // 顶点信息 Arcnode *firstarc; // 指向第一条依附该顶点的弧 } vnode, adjlist[MAX_VERTEX_NUM];
7.2.2 邻接表 • 邻接表的存储实现 (3)图的邻接表存储类型: typedef struct { adjlist vertices; int vexnum, arcnum; int kind; // 图的种类标志 } ALGraph; ALGraph G;
7.2.2 邻接表 • 建立无向图G的邻接表的算法概要: (1)、给顶点表中顶点域赋值,指针域赋值 G.VErtices[i].data=getchar(); G.VErtices[i].firstarc=NULL; (2)、读入边的邻接顶点编号i,j: ① 生成结点s; 前插法建表;s->nextarc= G.VErtices[i].firstarc; G.VErtices[i].firstarc=s; ②生成结点s; 前插法建表;…………. 3、重复第二步。
7.2.2 邻接表 • 建立无向网络(边带权图)G的算法详解: void Creatadilist(ALGraph &G) { int i,j,k;ArcNode *s; scanf(“%d,%d,%d”,G.VExnum,G.arcnum,G.kind); for(i=1;i<=G.VExnode;i++) {G.VErtices[i].data=getchar(); G.VErtices[i].firstarc=NULL;} 见下页 图示
7.2.2 邻接表 • 建立无向网络(边带权图)G的算法详解: 接上页 for(k=0;k<G.arcnum;k++) {scanf(“%d%d”,&i,&j); s=new ArcNode; s->adjVEx=j; s->info=NULL; s->nextarc= G.VErtices[i].firstarc; G.VErtices[i].firstarc=s; …………. } } 图示
7.2.2 邻接表 • 邻接表的特点 (1)对于顶点多边少的图采用邻接表存储节省空间;空间复杂度O(n+e)。 (2)容易找到任一顶点的第一个邻接点。
7.2.2 邻接表 • 图的存储结构总结 在不同的存储结构下,实现各种操作的效率可能是不同的。所以在求解实际问题时,要根据求解问题所需操作,选择合适的存储结构。
第七章 图 7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的连通性问题 7.5 有向无环图的应用 7.6 最短路径
7.3 图的遍历 图的遍历是指:从图的某一顶点出发访问图中的所有顶点,且每个顶点仅访问一次。 7.3.1、深度优先搜索 7.3.2、广度优先搜索
7.3.1 深度优先搜索 • 深度优先搜索的示例演示 v1 v2 v1 v2 v7 v7 v6 v6 v3 v3 v9 v8 v9 v8 v5 v4 v5 v4 Visited[9] 1 1 1 1 1 1 1 1 1