第一课数据结构 第7章 图2图的遍历
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
根据该算法用及图7-14中的邻接矩阵,可以得到图G7的 广度优先搜索序列,若从顶点1 出发,广度优先搜索序 列为:1,2,3, 4,5, 6,7,8。若从顶点3出发,广 度优先搜索序列为:3, 1, 6, 7, 2, 8, 4, 5。
算法描述如下:
void bfs( int i) //从顶点i出发遍历
例如,对下图所示无向图G7,从顶点1出发 的深度优先搜索遍历序列可有多种,下面仅 给出三种,其它可作类似分析。
1
1, 2, 4, 8, 5, 6, 3, 7 1, 2, 5, 8, 4, 7, 3, 6 1, 3, 6, 8, 7, 4, 2, 5
2
4
5
3
6 7
可以看出,从某一个顶点出发的遍 历结果是不唯一的。但是,若我们 给定图的存贮结构,则从某一顶点 出发的遍历结果应是唯一的。
for (j=1; j<=n; j++)
if ((A[i][j]==1)&&(!visited[j]))
{ visit(v[j]) ; visited[j]=1 ; r++; q[r]=j ;}
}}
2. 用邻接表实现图的广序优先搜索遍历
1
1
2
3
2
3
4
5
6
4
7
5
6
8
7
无向图 G7
8
2
3^
1
4
5^
1
6
7^
2
8^
2
8^
3
8^
3
8^
4
5
6
7^
G7 的邻接表
可以得到图G7的广度优先搜索序列,若从顶点1出发, 广度优先搜索序列为:1,2,3,4,5,6,7,8,若 从顶点7出发,广度优先搜索序列为:7,3,8,1,6, 4,5,2。
算法描述如下:
void BFS1(int i)
{ int q[n+1] ;
8 无向图 G7
深度优先遍历算法描述
void dfs(Graph G,vtx *v) { /*从v出发深度优先遍历图g*/
visit(v); visited[v] = 1; w=FIRSTADJ(G,v); //w为v的邻接点 while (w!=0) { //当邻接点存在时
if (!visited[w]) dfs(G,w);
}
用上述算法和无向图G7,可以描述从顶点1出发的 深度优先搜索遍历过程,其中实线表示下一层递 归调用,虚线表示递归调用的返回。
可以得到从顶点1的遍历结果为 1, 2, 4, 8, 5, 6, 3, 7。 同样可以分析出从其它顶点出发的遍历结果。
DFS(1)
DFS(2)
DFS(4)
DFS(8)
DFS(5)
1
2
4
5
3
6 7
8 无向图 G7
DFS(6)
DFS(3)
邻接矩阵深度优先搜索示意图
DFS(7)
2.用邻接表实现图的深度优先搜索
仍以无向图G7 为例,来说明算法的实现, G7的邻接表见下图:
1
1
2
2
3
3
4
5
6
4 75
6
8
7
无向图 G7
8
2
3^
1
4
5^
1
6
7^
2
8^
2
8^
3
8^
3
8^
4
5
6
7^
G7 的邻接表
7.3.1深度优先搜索遍历
1. 深度优先搜索思想
(1)首先访问顶点i,并将其访问标记置为访问过, 即visited[i] =1; (2) 然后搜索与顶点i有边相连的下一个顶点j, 若j未被访问过,则访问它,并将j的访问标记置 为访问过,visited[j]=1,然后从j开始重复此过 程,若j已访问,再看与i有边相连的其它顶点; (3) 若与i有边相连的顶点都被访问过,则退回 到前一个访问顶点并重复刚才过程,直到图中 所有顶点都被访问完为止。
3
其中实线表示下一层递归,虚线 4 5 6
7
表示递归返回,箭头旁边数字表
示调用的步骤。遍历序列为 7, 3, 1, 2, 4, 8, 5, 6。
8 无向图 G7
DFS1(7) 1 DFS1(3) 2 14
DFS1(1) 3 DFS1(2)
13
12
4 DFS1(4) 5 DFS1(8) 6 DFS1(5)
for(int i=1;i<=n;i++) if(!visited[i]) bfs(i) ;
for(int i=1;i<=n;i++) 或 if(!visited[i])
bfs1(i);
分析上述过程,每个顶点至多进一次队列。遍历图的过程实 质上是通过边或弧找邻接 点的过程、因此广度优先搜索遍历 图的时间复杂度和深度优先搜索遍历相同,两者不同之 处仅 仅在于对顶点访问的顺序不同。
7
11
10
8 DFS1(6)
9
邻接表深度优先搜索示意图
3. 非连通图的深度优先搜索
在每个连通分量或每个强连通分量中都选一个顶点, 进行深度优先搜索遍历,最后将每个连通分量或每个 强连通分量的遍历结果合起来,则得到整个非连通图 的遍历结果。
遍历算法实现与连通图的只有一点不同,即对所有顶 点进行循环,反复调用连通图的深度优先搜索遍历算 法即可。具体实现如下:
dfs1(p->adjvex);p=p->next;
}
邻接表深度优先搜索演示
}
而当以邻接表作图的存储结构时,找邻接点所需
时间为O(e),其中e为无向图中边 的数或有向图
中弧的数。由此,当以邻接表作存储结构时,深
度优先搜索遍历图的时间复 杂度为O(n+e)。
1
用刚才算法,可以描述从顶点7
2
出发的深度优先搜索遍历示意图,
w=NEXTADJ(g,v,w);//求下一邻接点 } } }//bfs
1. 用邻接矩阵实现图的广度优先搜索遍历
1
2
4
5
3
6 7
8
01100000 10011000 10000110 01000001 01000001 00100001 00100001 00011110
无向图 G7
无向图 G7 的邻接矩阵
w=NEXTADJ(G,v,w);//找下一邻接点 } }
1. 用邻接矩阵实现图的深度优先搜索
1
2
4
5
3
6 7
8 无向图 G7
01100000 10011000 10000110 01000001 01000001 00100001 00100001 00011110
邻接矩阵的深度优先搜索演示
无向图 G7 的邻接矩阵
精品课件!
精品课件!
作业
已知图的邻接矩阵如右图, 从顶点0出发,写出按深度 优先遍历的结点序列。并画 出像讲义中的示意图,其中 实线表示下一层递归,虚线 表示递归返回,箭头旁边数 字表示调用的步骤。
写出按广度优先遍历右图的 结点序列并画出每次访问一 个结点的时候队列中的节点 序列。
//定义队列
int f,r ; E_NODE *p ; //P为搜索指针
f=r=0 ; visit(head[i]) ; visited[i]=1 ; r++; q[r]=i ; //进队
while (f<r)
{ f++ ; i=q[f] ; p=head[i].link ;
while (p!=NULL)
在无向图G7中,从顶点1出发的广度优先 搜索遍历序列举三种为:
1
1, 2, 3, 4, 5, 6, 7, 8
1, 3, 2, 7, 6, 5, 4, 8
2
3
1, 2, 3, 5, 4, 7, 6, 8
4
5
6
7
8 无向图 G7
和深度优先搜索类似,在遍历的过程中也需要一个访问标志数 组。并且,为了顺次访 问路径长度为2、3、…的顶点,需附设 队列以存储已被访问的路径长度为1,2,…的顶点。广 度优先 遍历的算法如下所示。 void bfs(Graph g ,vtx * v) {
算法描述为下面形式:
void dfs1(int i) { link *p; visit(head[i]) ; //输出访问顶点
visted[i]=1; //全局数组访问标记置为1表示已访问
p=head[i].link;
while (p!=NULL) {
if (!visited[p->adjvex])
visit(v); visited[v]=1; INIQUEUE(Q); ENQUEUE(Q,v); while (!EMPTY(Q)) { DLQUEUE(Q,v); //队头元素出队
w=FIRSTADJ(g,v);//求v的邻接点 while (w!=0){
if (!visited[w]) { visit(w); visited[w]=1; ENQUEUE(Q,w); }
邻接矩阵存储时的算法描述为下面形式:
void dfs (int i) // 从顶点i 出发遍历 {
int j; visit(i); //输出访问顶点 visited[i]=1; //全局数组访问标记置1表示已经访问 for(j=1; j<=n; j++)
if ((A[i][j]= =1)&&(!visited[j])) dfs(j);
for(int i=1;i<=n;i++)
if(!visited[i])
或者
dfs(i) ;
for(int i=1;i<=n;i++) if(!visited[i]) dfs1(i);
8.3.2 广度优先搜索遍历
1. 广度优先搜索的思想
广度优先搜索遍历类似于树的按层次遍历。设图 G的初态是所有顶点均未访问,在G 中任选一顶 点i作为初始点,则广度优先搜索的基本思想是: (1) 首先访问顶点i,并将其访问标志置为已被访 问,即visited[i]=1; (2) 接着依次访问与顶点i有边相连的所有顶点W1, W2,…,Wt; (3) 然后再按顺序访问与W1,W2,…,Wt有边 相连又未曾访问过的顶点; 依此类推,直到图中所有顶点都被访问完为止 。
{ int Q[n+1] ; //Q为队列
int f,r,j ;
// f,r分别为队列头,尾指针
f来自百度文库r=0 ;
//设置空队列
visit(v[i]) ;
// 输出访问顶点
visited[i]=1 ; //全局数组标记置1表示已经访问
r++; q[r]=i ; //入队列
while (f<r) {
f++; i=q[f] ; //出队列
7.3 图的遍历
在图中有回路,从图中某一顶点出发访问 图中其它顶点时,可能又会回到出发点, 而图中可能还剩余有顶点没有访问到。
我们可以设置一个全局型标志数组visited 来标志某个顶点是否被访问过,未访问的 值为0,访问过的值为1。
图的遍历有两种方法:深度优先搜索遍历 (DFS)和广度优先搜索遍历(BFS)。
{ if (!visited[p->adjvex]){
visit(head[p->adjvex].vertex;
visited[p->adjvex]=1; r++;q[r]=p->adjvex ;
} p=p->next;}}}
邻接表的广度优先搜索演示
3. 非连通图的广度优先搜索
可以在每个连通分量或每个强连通分量中都选一个顶点,进行 广度优先搜索遍历,最后将每个连通分量或每个强连通分量的 遍历结果合起来,则得到整个非连通图或非强连通图的广度优 先搜索遍历序列。具体可以表示如下: