410 likes | 552 Views
第七章 图. 一、图的定义. 图是一种数据元素间为多对多关系的数据结构,加上一组基本操作构成的抽象数据类型。. ADT Graph. { 数据对象 V : V 是具有相同特性的数据元素的集合,称为顶点集。 数据关系 R : R={VR} VR={<v,w>|v,w(-V 且 P(v,w),<v,w> 表示从 v 到 w 的弧,谓词 P(v,w) 定义了弧 <v,w> 的意义或信息 }. 基本操作 P :. CreateGraph(&G,V,VR); 初始条件: V 是图的顶点集, VR 是图中弧的集合。 操作结果:按 V 和 VR 的定义构造图 G
E N D
一、图的定义 图是一种数据元素间为多对多关系的数据结构,加上一组基本操作构成的抽象数据类型。
ADT Graph { 数据对象V :V是具有相同特性的数据元素的集合,称为顶点集。 数据关系R: R={VR} VR={<v,w>|v,w(-V且P(v,w),<v,w>表示从v到w的弧,谓词P(v,w)定义了弧<v,w>的意义或信息}
基本操作P: • CreateGraph(&G,V,VR); • 初始条件:V是图的顶点集,VR是图中弧的集合。 • 操作结果:按V和VR的定义构造图G • DestroyGraph(&G); • 初始条件:图G存在 • 操作结果:销毁图G • LocateVex(G,u); • 初始条件:图G存在,u一G中顶点有相同特征 • 操作结果:若G中存在顶点u, 则返回该顶点在图中位置;否则返回其它信息。 • GetVex(G,v); • 初始条件:图G存在,v是G中某个顶点 • 操作结果:返回v的值。
PutVex(&G,v,value); • 初始条件:图G存在,v是G中某个顶点 • 操作结果:对v赋值value • FirstAdjVex(G,v); • 初始条件:图G存在,v是G中某个顶点 • 操作结果:返回v的第一个邻接顶点。若顶点在G中没有邻接顶点,则返回“空” • NextAdjVex(G,v,w); • 初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点。 • 操作结果:返回v的(相对于w的)下一个邻接顶点。若w是v的最后一个邻接点,则返回“空”
InsertVex(&G,v); • 初始条件:图G存在,v和图中顶点有相同特征 • 操作结果:在图G中增添新顶点v • DeleteVex(&G,v); • 初始条件:图G存在,v是G中某个顶点 • 操作结果:删除G中顶点v及其相关的弧 • InsertAcr(&G,v,w); • 初始条件:图G存在,v和w是G中两个顶点 • 操作结果:在G中增添弧<v,w>,若G是无向的,则还增添对称弧<w,v>
DeleteArc(&G,v,w); • 初始条件:图G存在,v和w是G中两个顶点 • 操作结果:在G中删除弧<v,w>,若G是无向的,则还删除对称弧<w,v> • DFSTraverser(G,v,Visit()); • 初始条件:图G存在,v是G中某个顶点,Visit是顶点的应用函数 • 操作结果:从顶点v起深度优先遍历图G,并对每个顶点调用函数Visit一次。一旦Visit()失败,则操作失败。 • BFSTRaverse(G,v,Visit()); • 初始条件:图G存在,v是G中某个顶点,Visit是顶点的应用函数 • 操作结果:从顶点v起广度优先遍历图G,并对每个顶点调用函数Visit一次。一旦Visit()失败,则操作失败。 • }ADT Graph
二、图的常用术语 对上图有:G1=(V1,{A1}) 其中:V1={v1,v2,v3,v4} A1={<v1,v2>,<v1,v3>,<v3,v4>,<v4,v1>}
如果用n表示图中顶点数目,用e表示边或弧的数目,则有:如果用n表示图中顶点数目,用e表示边或弧的数目,则有: 对于无向图,e的取值范围是0到n(n-1)/2,有n(n-1)/2条边的无向图称为完全图。 对于有向图,e有取值范围是0到n(n-1)。具有n(n-1)条弧的有向图称为有向完全图。 有很少条边或弧的图称为稀疏图,反之称为稠密图。
对有向图, 如果每一对顶点之间都有通路,则称该图为强连通图。 环 入度 出度
有关概念: Weight network Graph Subgraph Cycle Path
顶点的位置 • 邻接点的位置
在图所示的各无向图中: (1)找出所有的简单环:(同一个环可以任一顶点作为起点)。 (2)哪些图是连通图?对非连通图给出其连通分量。 (2):(a)、(c)、(d)是连通图,(b)不是连通图,因为从1到2没有路径 连通图的生成树
图的存储结构 • 数组表示法 • 邻接表 • 十字链表 • 邻接多重表
数组表示法 用两个数组分别存储数据元素(顶点)的信息和数据元素之间的关系(边或弧)的信息。 // 图的数组(邻接矩阵)存储表示 #define INFINITY INT_MAX //最大值无穷大 #define MAX_VERTEX_NUM 20 //最大顶点个数 typedef enum{DG,DN,AG,AN} GraphKind;//有向图,有向网,无向图,无向网
typedef struct ArcCell{ VRType adj; //VRType是顶点关系类型。对无权图,用1或0表示相邻否,对带权图,则为权值类型 InfoType *info; //该弧相关信息的指针 }ArcCell,AdjMatrix[max_vertex_num][max_vertex_num]; tpyedef struct{ VertexType vexs[MAX_VERTEX_NUM]; //顶点向量 AdjMatrix arcs; //邻接矩阵 int vexnum,arcnum; //图的当前顶点数和弧数 GraphKind kind; //图的种类标志 }MGraph;
关于邻接矩阵 1 压缩存储 2 判定顶点间关系 • 无向图 • 顶点vi的度是邻接矩阵中第i行(列)的元素之和 • 有向图 • 第I行的元素之和为顶点vi的出度,第j列的元素之和为顶点vj的入度 3 网的邻接矩阵
算法7.1 7.2 CreateUDN(Mgraph &G) { Scanf(&G.vexnum, &G.arcnum, &IncInfo); For (I=0; I<G.vexnum; ++ I) scanf(&G.vexs[I]); For (I=0; I<G.vexnum; ++ I) for (j=0; j<G.vexnum; ++j) G.arcs[I][j] = {INFINITY, NULL}; For (k=0; k<G.arcnum; ++k) { Scanf(&v1, &v2, &w); I = LocateVex(G, v1);J=LocateVex(G, v2); G.arcs[I][j].adj = w; If (IncInfo) Input(*G.arcs[I][j].info); G.arcs[j][I] = G.arcs[I][j]; } Return OK; }
表结点 adjvex data nextarc firstarc info 头结点 邻接表 邻接表是图的一种链式存储结构。 在邻接表中,对图中每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点vi的边(对有向图是以顶点vi为尾的弧)。每个结点由三个域组成,其中邻接点域(adjvex)指示与顶点vi邻接的点在图中的位置(序号),链域(nextarc)指示下一条边或弧的结点;数据域(info)存储和边或弧相关的信息,如权值等。每个链表上附设一个表头结点,包含链域(firstarc)指向链表中第一个结点,还设有存储顶点vi的名或其它有关信息的数据域(data)。如: 例
#define MAX_VERTEX_NUM 20 typedef struct ArcNode{ int adjvex; //该弧所指向的顶点的位置 struct ArcNode *nextarc; //指向下一条弧的指针 InfoType *info; //该弧相关信息的指针 }ArcNode; typedef struct VNode{ VertexType data; //顶点信息 ArcNode *firstarc; //指向第一条依附该顶点的弧的指针 }VNode,AdjList[MAX_VERTEX_NUM]; typedef struct { AdjList vertices; int vexnum,arcnum; //图的当前顶点数和弧数 int kind; //图的种类标志 }ALGraph;
例p164 • 例 • 逆邻接表 • 优缺点
十字链表 弧结点 顶点结点 存储表示 p165
邻接多重表 边结点 顶点结点 存储表示 p167
图的遍历 • Depth First Search • Breadth First Search
DFS • 搜索思想 • 例 • 如何实现 • 数据结构上 • Algorithm 7.4 7.5 • 时间复杂度 • 数组表示时:O(n^2) • 邻接表 O(n+e)
BFS • 搜索思想 • 例 • 如何实现 • 数据结构上 • Algorithm 7.6 • 时间复杂度 • 数组表示时:O(n^2) • 邻接表 O(n+e)
无向图的连通分量和生成树 • 连通 非连通图的 遍历问题 • 连通分量 • 连通图的生成树 • 非连通图的生成森林
非连通图的DFS生成森林算法 Void DFSForest(Graph G, CSTree &T){ T=NULL; For (v=0; v<G.vexnum; ++v) visited[v] = FALSE; For (v=0; v<G.vexnum; ++v) If (!visited[v]) { p = (CSTree) malloc (sizeof(CSNode)); *p = {GetVex(G, v), NULL, NULL}; if (!T) T = p; else q -> nextsibling = p; q = p; DFSTree(G, v, p);} }
最小生成树 • 应用背景
最短树的Kruskal算法 (1) 对属于E的边进行排序得 (2) 初始化操作 (3)若t=n-1,则转(6),否则转(4) (4)若 (6)输出T,w,停止 例
最短树的Prim算法 (1) 初始化操作 (2)若k>=n, 则做:[输出T,结束] 否则做:
最短路径的Dijkstra算法 (1) 初始化操作 (2)若 则做:[打印S后停止],否则转(3)。
应用例子 某公司在六个城市C1,…C6有分公司,从Ci到Cj的直接航程票记在下述矩阵的(i,j)位置上。该公司想要一张任两城市间的票价最便宜的路线表,试作出这样的表格
应用例子 在一河岸有狼、羊、菜,摆渡人要将他们渡过河去,但由于他的船太小,每次只能载一样东西,显然,狼和羊、羊和菜都不能在无人监视的情况下放在一起,问摆渡人如何将他们渡过河去?
按顺序输入顶点对:(1,2),(1,6),(2,6),(1,4),(6,4),(1,3),(3,4)(6,5),(4,5),(1,5),(3,5)。按顺序输入顶点对:(1,2),(1,6),(2,6),(1,4),(6,4),(1,3),(3,4)(6,5),(4,5),(1,5),(3,5)。 画出相应的邻接表。 并写出在该邻接表上,从顶点4开始搜索所得的DFS和BFS序列,及DFS和BFS生成树。
对图所示的连通图,请分别用Prim和Kruskal算法构造其最小生成树。对图所示的连通图,请分别用Prim和Kruskal算法构造其最小生成树。
DFS和BFS遍历各采用什么样的数据结构来暂存顶点?当要求连通图的生成树的高度最小,应采用何种遍历?DFS和BFS遍历各采用什么样的数据结构来暂存顶点?当要求连通图的生成树的高度最小,应采用何种遍历? 对n个顶点的无向图和有向图,采用邻接矩阵和邻接表表示时,如何判别下列有关问题? (1) 图中有多少条边? (2)任意两个顶点i和j是否有边相连? (3) 任意一个顶点的度是多少?