第七章图
7.1抽象数据类型图的定义
7.2图的存储表示
7.3图的遍历
7.4最小生成树
7.5重(双)连通图和关节点
7.6两点之间的最短路径问题
7.7拓扑排序
7.8关键路径
7.1抽象数据类型图的定义
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>的意义或信息}
}
名词和术语
弧头、弧尾、弧、有向图
边,无向图
网,子图
完全图,稀疏图,稠密图
邻接点,度,入度,初度
路径,路径长度,简单路径,简单回路
连通图,连通分量,强连通图,强连通分量
生成树,生成森林
若<v,w>∈VR,则<v,w>表示匆匆顶点v到顶点w的一条弧,称顶点v为弧尾,顶点w为弧头。有顶点集和弧集构成的图称为有向图。
若<v,w>∈VR必有<w,v>∈VR,则称(v,w)为顶点v和顶点w之间存在一条边。
由顶点集和边集构成的图称作无向图。
弧或边带权的图分别称作有向网或无向网。
设图G=(V,{VR})和图G’=(V’,{VR’}),且V’包含于V且VR包含于VR’则称G’为G的子图。
假设图中有n个顶点,e条边,则
含有e=n(n-1)/2条边的无向图称作完全图
含有e=n(n-1)条弧的有向图称作有向完全图
若边或弧的个数e<nlogn,则称作稀疏图,否则称作稠密图。
无向图
假若顶点v和顶点w之间存在一条边,则称顶点v和顶点w互为邻接点,边(v,w)和顶点v和w相关联。
和顶点v关联的边的数目定义为边的度。
对有向图来说,
以顶点v为弧尾的弧的数目定义为顶点的出度,以顶点v的弧头的弧的数目定义为顶点的入度。度(TD)=入度(OD)+出度(ID)
设图G=(V,{VR})中的一个顶点序列{u=vi,0, vi,1, …, vi,m = w}中(vi,j-1, vi,j)∈VR,1<=j<=m,则称从顶点u到顶点v之间存在一条路径,路径上边的数目称作路径长度。
若序列中的顶点不重复出现,则称作简单路径。
若u=w,则称这条路径为回路或简单回路。
若图G中任意两个顶点之间都有路径相同,则称此图为连通图;
若无向图为非连通图,则图中各个极大连通图子图称作此图的连同分量。
对有向图,若任意两个顶点之间都存在一条有向路径,则称此有向图为强连通图,否则,其各个强连通子图称作它的强连通分量。
假设一个连通图有n个顶点和e条边,其中n-1条边和n个顶点构成一个极小连通子图,称该极小连通子图为此连通图的生成树。
对非连通图,则称各个连同分量的生成树的集合为此非连通图的生成森林。
基本操作:
结构的建立和销毁
CreateGraph(&G, V, R);
DestroyGraph(&G);
对顶点的访问操作
LocateVex(G, u);
GetVex(G, v);
PutVex(&G, v, value);
对邻接点的操作
FirstAdjVex(G, v);
NextAdjVex(G, v, w);
插入或删除顶点
InsertVex(&G, v);
DeleteVex(&G, v);
插入和删除弧
InsertArc(G, v, w);
DeleteArc(&G, v, w);
遍历
DFSTraverse(G, v, Visit());
BFSTraverse(G, v, Visit());
对顶点的访问操作
LocateVex(G, u); //若G中存在顶点u,则返回该顶点在图中位置;否则返回其它信息。
GetVex(G, v); //返回v的值
PutVex(&G, v, value); //对v赋值value
对邻接点的操作
FirstAdjVex(G, v); //返回v的第一个邻接点。若该顶点在G中没有邻接点,则返回“空”。
NextAdjVex(G, v, w); //返回v的(相对于w的)下一个邻接点。若w是v的最后一个邻接点,则返回“空”。
插入或删除顶点
InsertVex(&G, v); //在图G中增添新顶点v。
DeleteVex(&G, v);//删除G中顶点v及其相关的弧。
插入和删除弧
InsertArc(&G, v, w); //在G中增添弧<v,w>,若G是无向的,则还增添对称弧<w,v>。
DeleteArc(&G, v, w);//在G中删除弧<v,w>,若G是无向的,则还删除对称弧<w,v>。
遍历
DFSTraverse(G, v, Visit()); //从顶点v起深度优先遍历图G,并对每个顶点调用函数Visit一次且仅一次。
BFSTraverse(G, v, Visit());//从顶点v起广度优先遍历图G,并对每个顶点调用函数Visit一次且仅一次。
7.2图的存储表示
一、图的数组(邻接矩阵)存储表示。
25_001 |
typedef struct ArcCell { VRType adj; //VRType是顶点关系类型,对无权图,用1或0表示相邻与否;对带权图,则为权值类型 InfoType *info; //该弧相关信息的指针 }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct { Vertex vexs[MAX_VERTEX_NUM]; AdjMatrix arcs; int vexnum, arenum; GraphKind kind; }MGraph; |
二、图的邻接表存储表示
25_002 |
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 vernum, arcnum; int kind; //图的种类标志 }ALGraph; |
三、有向图的是自链表存储表示
25_003 |
typedef struct ArcBox { int tailvex, headvex; //该弧的弧尾和头顶点的位置 struct ArcBox *hlink, *tlink; //分别指向下一个弧头相同弧尾相同弧的指针域 InfoType *info; //该弧相关信息的指针 }ArcBox;
typedef struct VexNode { VertexType data; ArcBox *firstin, *firstout; }VexNode;
typedef struct { VexNode xlist[MAX_VERTEX_NUM]; int vexnum, arcnum; //有向图的当前顶点数和弧数 }OLGraph; |
一、无向图的邻接多重表存储表示
25_004 |
typedef struct Ebox { VisitIf mark; //访问标记 int ivex,jvex; //访问依附两个顶点的位置 struct EBox *ilink, *jlink; InfoType *info; //该边信息指针 }EBox;
typedef struct VexBox { VertexType data; EBox *firstedge; //指向第一条依附该顶点的边 }VexBox;
typedef struct { VexBox adjmulist[MAX_VERTEX_NUM]; int vexnum, edgnum; }AMLGraph; |
7.3图的遍历
从图中某个顶点出发游历图,访遍图中其余顶点,并且使图中的每个顶点仅被访问一次的过程。
深度优先搜索
广度优先搜索
遍历应用举例
从图中某个顶点V0 出发,访问此顶点,然后依次从V0 的各个未被访问的邻接点出发深度优先搜索遍历图。,直至图中所有和V0有路径想通的顶点都被访问到,若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作为起始点,重复上述过程,直至图中所有顶点都被访问到为止。
26_001 |
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 } } }
void DFS(Graph G, int v) { 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 } } } |