第七章、图

  • 格式:ppt
  • 大小:3.13 MB
  • 文档页数:95

下载文档原格式

  / 50
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

V1
V2 V4 V5 V8 V6
V3 V7
深度遍历:V1V3 V7 V6 V2 V5 V8 V4 adjvex next 2 ^ 4 6 2 2 3 3 4 ^ ^
注意:根据邻接表 来决定访问次序
vexdata firstarc 1
2 3 4 5 1 2 3 4 5 6 7 3 5 7 8 8 7
沿另外某个路径绕回到先前已访问过的顶点。

解决办法 为了避免重复访问图中的顶点,必须在遍历过程中对已访问的顶点进行
标记。为此,可设立一个辅助数组visited[n],它的初始值置为“假”,一
旦某个顶点vi被访问,便将visited[i]置为“真”。

Байду номын сангаас
遍历方式
图的遍历通常有深度优先搜索和广度优先搜索两种遍历方式,它们对无
向图和有向图都适用
一、深度优先遍历
无向图的例子
深度优先遍历算法--递归算法
开始 标志数组初始化 Vi=1 Vi访问过 Y Vi=Vi+1 N Vi==Vexnums Y 结束 N 开始 访问V0,置标志 求V0邻接点
有邻接点w
N
结束 Y
DFS
Y
W访问过 N wV0 DFS
求下一邻接点

例 3 强连通图 5 6 1 2 4 3 连通图 5 6
例 2 1 4 3 5 6 非连通图 连通分量
图的基本操作(P.117)
(1) CreateGraph(G):图的创建操作。 初始条件:无。 操作结果:生成一个没有顶点的空图G。 (2) LocateVex(G,v):顶点定位函数。 初始条件:G已经存在,v是一个顶点。 操作结果:返回v在G中的位置,若G中无此顶点,则返回“空”。 (3) FirstAdj(G,v):求第一个邻接点函数。 初始条件:G已经存在,v是G中某个顶点。 操作结果:返回 v 的第一个邻接点,若 v 在 G 中无邻接点,则返回 “空”。 (4) NextAdj(G,v,w):求下一个邻接点函数。 初始条件:G已经存在,v是G中某个顶点,w是v的一个邻接点。 操作结果:返回v的邻接点中w之后的下一个邻接点,若无下一邻 接点,则返回“空”。 ……
例 1 3 2 5 4 7 6

子图——如果图G(V,E)和图G‘(V’,E‘),满足:

V’V E’E
2 1 4 3 5 6 图与子图
则称 例G‘为G的子图
3
5 6


连通——从顶点V到顶点W有一条路径,则说V和W 是连通的 连通图——图中任意两个顶点都是连通的叫~ 连通分量——非连通图的每一个连通部分叫~ 强连通图——有向图中,如果对每一对Vi,VjV, ViVj,从Vi到Vj 和从Vj到 Vi都存在路径,则称G 是~ 例
例 1 3 2 5 4 7 6 1 2 4 3 G1 顶点2入度:1 出度:3 顶点4入度:1 出度:0 5 6

G2
顶点5的度:3 顶点2的度:4

权——与图的边或弧相关的数叫权 网——带权的图叫网
1 2 2 61 3 3 81 9 5 4 5
1
一个带权有向图





路径——路径是顶点的序列V={Vi0,Vi1,……Vin},满足 (Vij-1,Vij)E 或 <Vij-1,Vij>E,(1<jn) 路径长度——沿路径边的数目或沿路径各边权值之和 回路——第一个顶点和最后一个顶点相同的路径叫回路 简单路径——序列中顶点不重复出现的路径叫~ 简单回路——除了第一个顶点和最后一个顶点外,其余 顶点不重复出现的回路叫~
Y
Vi=Vi+1 N
结束
//------- 按广度优先非递归遍历图G。使用辅助队列Q 和访问标志数组visited。
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尚未访问 EnQueue(Q, v); // v入队列 while (!QueueEmpty(Q)) { DeQueue(Q, u); // 队头元素出队并置为u visited[u] = TRUE; Visit(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); // u的尚未访问的邻接顶点w入队列Q };//if }//while }//if } // BFSTraverse
2 1 4 3 5 6
路径:1,2,3,5,6,3 路径长度:5 简单路径:1,2,3,5 回路:1,2,3,5,6,3,1 简单回路:3,5,6,3 路径:1,2,5,7,6,5,2,3 路径长度:7 简单路径:1,2,5,7,6 回路:1,2,5,7,6,5,2,1 简单回路:1,2,3,1
G1
1
^
1
^
6 7
8
^
^
6
5
8
^
例 V2 V4
V1
V3 V5 V8 V6 V7 深度遍历:V1V3 V7 V6 V2 V4 V8 V5 adjvex next 2 ^
vexdata firstarc 1
2 3 4 5 1 2 3 4 5 6 7 ^ ^ 3 4 7 8 8 7 ^ ^
^
6 ^
void DFS(ALGraph G, int v) { // 从第v个顶点出发递归地深度优先遍历图G。 visited[v] = TRUE; VisitFunc(G.vertices[v].data); // 访问第v个顶点 for ( p=G.vertices[ v ].firstarc; p; p=p->nextarc; ) {
C
D
E
F 其中v是数据元素,称为顶点(vertex),P(v,w)表示从顶点v
到顶点w有一条直接通路,即v和w之间存在一个关系,用顶点偶对 <v,w>来表示。 通常可以根据图的顶点偶对将图分为有向图和无向图。
有向图
如下图(a)是一个有向图G,可形式地表示为:
G=(V,E) V={a,b,c,d,e} E={<a,b>,<a,c>,<a,e>,<c,d>,<c,e>,<d,a>, <d,b>,<e,d>}
第二节、图的存储结构
图的存储结构
邻接矩阵
邻接表
邻接矩阵(数组表示法)
有向图邻接矩阵举例
无向图邻接矩阵举例
无向网的邻接矩阵表示
邻接矩阵表示法的特点
邻接矩阵表示法的特点



例、对n个顶点的无向图采用邻接矩阵 表示时,如何判别下列有关问题? 1) 图中有多少条边? 2) 任意两个顶点i和j是否有边相连? 3) 任意一个顶点的度是多少?
w = p->adjvex;
if (!visited[w]) DFS(G, w);
// 对v的尚未访问的邻接顶点w递归调用DFS
}
}//DFS
二、广度优先遍历
广度优先遍历BFS—Breadth First Search方法:从 图的某一顶点V0出发,访问此顶点后,依次访问V0的各 个未曾访问过的邻接点;然后分别从这些邻接点出发, 广度优先遍历图,直至图中所有已被访问的顶点的邻接 点都被访问到;若此时图中尚有顶点未被访问,则另选 图中一个未被访问的顶点作起点,重复上述过程,直至 图中所有顶点都被访问为止
第七章、图
本章内容

第一节、基本概念 第二节、图的存储结构 第三节、图的遍历 第四节、图的应用
第一节 图的定义和基本术语

图(Graph)G是由两个集合V和E组成的偶对,表示为
G=(V,E)
其中V是有限非空的顶点集合,E是由顶点偶对表示的关系集合。 A 一个图可以形式化定义为: B G=(V,E) V={v|v data object} E={<v,w>| v,w V∧P(v,w)}
答:对于n个顶点的无向图和有向图,用邻接矩 阵表示时: 1)设m为矩阵中非零元素的个数,则无向图的边 数=m/2 2)在矩阵中第i行,第j列的元素若为非零值,则该 两顶点有边相连。 3)对于无向图,任一顶点i的度为第i行中非零元 素的个数。
邻接矩阵法的实现
P.119
2、邻接表(P.119)
对于图G1中每个顶点vi,将所有邻接于vi的顶点vj链成一个单 链表,这个单链表就称为顶点vi的邻接表,再将所有顶点的邻接表 表头放到数组中,就构成了图的邻接表。
第三节、图的遍历

给出一个图G和其中的任意一个顶点v,从v出
发访问图G中的所有顶点,且每个顶点仅访问
一次,这一过程叫做图的遍历。

根据每个顶点在遍历过程中访问的先后顺序
,可以得到由图的所有顶点组成的序列,这
个序列称为遍历序列。

复杂性 与树的遍历相比,图的遍历要复杂得多。因为图的任一顶点都可能与其 余的顶点相邻接,所以在访问了某个顶点之后,在以后的访问过程中又可能
邻接表表示存储结构
P。120
邻接表的优点
边(或弧)稀疏时,节省空间; 边(或弧)相关的信息多时,节省时间 容易求得当前定点的第一个邻接点、下一个邻 接点
结点的度:无向图中顶点Vi的度为第i个单链表 中的节点数;
有向图中:顶点Vi的出度为第i个单链表中的节 点个数;顶点Vi的入度为整个单链表中邻接点域 是i的结点个数。
使用邻接表存储的图广度遍历 vexdata firstarc 例 2 1 3 4 1 2 3 4
1
2 3 4 5 f
4 5
adjvex next 3
1 1 1 3 f 4 3 0 1 2 3 4 5 ^ ^ ^
2
^
5
5 4
5
5
2
^
f 1 0 1 2 3 4 5 r
4 0 1 2 3 4 5
r
r
遍历序列:1 4 3
例 V2 V4 V8 广度遍历:V1 V2 V3 V4 V5 V6 V7 V8 V5 V6 V1 V3 V7 V4 V8 广度遍历:V1 V2 V3 V4 V6 V7 V8 V5 例 V2 V5 V6 V1 V3 V7
开始
开始 标志数组初始化 Vi=1 Y Vi访问过 N BFS BFS 访问V0,置标志 初始化队列 V0入队 队列空吗 N 队头V出队 求V邻接点w N Vi==Vexnums Y 结束 w存在吗 Y w访问过 N a Y a 访问w,置标志 w入队 V下一邻接点w
E是有向边(也称弧)的有限集合,弧是顶点的 有序对,记为<v,w>,v,w是顶点,v为弧尾,w为弧头
a
e c (a) 有向图G d b
无向图
如图(b)所示的是一个无向图G,可形式地表示为: G=(V,E)
V={a,b,c,d}
E = {(a,b),(a,c),(a,d),(b,d),(c,d)}
E(G)是边的有限集合,边是顶点的无序对,记为(v,w)或 (w,v),并且(v,w)=(w,v)
2
^
6 7
8
8
void DFSTraverse(ALGraph G)
{
// 对以邻接表表示的图G作深度优先遍历。
bool visited[G.vexnum];
// 附设访问标志数组
for (v=0; v<G.vexnum; ++v) visited[v] = FALSE; // 访问标志数组初始化 for (v=0; v<G.vexnum; ++v) if (!visited[v]) DFS(G, v); // 对尚未访问的顶点调用 DFS }
a
c b
d (b) 无向图G


有向完全图——n个顶点的有向图最大边数是 n(n-1) 无向完全图——n个顶点的无向图最大边数是 n(n-1)/2 2 2
例 1
有向完全图
3
1
无向完全图
3

顶点的度

无向图中,顶点的度TD为与每个顶点相连的边数 有向图中,顶点的度分成入度与出度 入度ID:以该顶点为头的弧的数目 出度OD:以该顶点为尾的弧的数目
遍历序列:1
遍历序列:1 4
vexdata firstarc 例 2 1 3 5 4 1 2 3 4 5
1
2 3 4 5
4 5
adjvex next 3
1 1 1 3 ^ ^ ^
2
^
5
5 4
2
^
f 4 3 2 0 1 2 3 4 5 r 遍历序列:1 4 3 2
f 3 2 0 1 2 3 4 5 r