概述
图的遍历是指从图中的任一顶点出发,对图中的所有顶点访问一次且只访问一次。图的遍历操作和树的遍历操作功能相似。图的遍历是图的一种基本操作,图的其它算法如求解图的连通性问题,拓扑排序,求关键路径等都是建立在遍历算法的基础之上。
由于图结构本身的复杂性,所以图的遍历操作也较复杂,主要表现在以下四个方面:
① 在图结构中,没有一个“自然”的首结点,图中任意一个顶点都可作为第一个被访问的结点。
② 在非连通图中,从一个顶点出发,只能够访问它所在的连通分量上的所有顶点,因此,还需考虑如何选取下一个出发点以访问图中其余的连通分量。
③ 在图结构中,如果有回路存在,那么一个顶点被访问之后,有可能沿回路又回到该顶点。
④ 在图结构中,一个顶点可以和其它多个顶点相连,当这样的顶点访问过后,存在如何选取下一个要访问的顶点的问题。
图的遍历通常有深度优先搜索和广度优先搜索两种方式,他们对无向图和有向图都适用。
1.深度优先搜索
深度优先搜索(Depth_Fisrst Search)遍历类似于树的先根遍历,是树的先根遍历的推广。
假设初始状态是图中所有顶点未曾被访问,则深度优先搜索可从图中某个顶点发v 出发,访问此顶点,然后依次从v 的未被访问的邻接点出发深度优先遍历图,直至图中所有和v 有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
以如下图的无向图G5为例,进行图的深度优先搜索:
G5
搜索过程:
假设从顶点v1 出发进行搜索,在访问了顶点v1 之后,选择邻接点v2。因为v2 未曾访问,则从v2 出发进行搜索。依次类推,接着从v4 、v8 、v5 出发进行搜索。在访问了v5 之后,由于v5 的邻接点都已被访问,则搜索回到v8。由于同样的理由,搜索继续回到v4,v2 直至v1,此时由于v1 的另一个邻接点未被访问,则搜索又从v1 到v3,再继续进行下去由此,得到的顶点访问序列为:
显然,这是一个递归的过程。为了在遍历过程中便于区分顶点是否已被访问,需附设访问标志数组visited[0:n-1], ,其初值为FALSE ,一旦某个顶点被访问,则其相应的分量置为TRUE。
1)邻接矩阵的存储方式实现:
1. // stdafx.h : include file for standard system include files,
2. // or project specific include files that are used frequently, but
3. // are changed infrequently
4. //
5.
6. #pragma once
7.
8. #include "targetver.h"
9. #include <stdio.h>
10. #include "stdlib.h"
11. #include <iostream>
12. using namespace std;
13.
14. //宏定义
15. #define TRUE 1
16. #define FALSE 0
17. #define NULL 0
18. #define OK 1
19. #define ERROR 0
20. #define INFEASIBLE -1
21. #define OVERFLOW -2
22.
23. #define INFINITY INT_MAX
24. #define MAX_VERTEX_NUM 30
25.
26.
27. typedef int Status ;
28. typedef int ElemType ;
29. typedef int VrType ;
30. typedef char VertexType ;
31. /************************************************************************/
32. /* 数组表示:邻接矩阵数据结构
33. */
34. /************************************************************************/
35.
36. typedef struct ArcCell{
37. //顶点关系类型,对无权图,0/1表示是否相邻,有权图表示权值
38. //弧相关信息的指针
39. }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
40.
41. typedef struct{
42. //顶点向量
43. //邻接矩阵
44. int vexnum,arcnum; //图的当前顶点数和弧数
45. }MGraph;
1. // Test.cpp : Defines the entry point for the console application.
2. //
3. #include "stdafx.h"
4.
5. bool visited[MAX_VERTEX_NUM]; //访问标识
6. Status (*VisitFunc) (int v); //函数变量
7. /************************************************************************/
8. /*
9. 确定顶点v在图G的位置
10. */
11. /************************************************************************/
12. int LocateVex(MGraph G,VertexType v)
13. {
14. for(int i = 0; i<G.vexnum; ++i) {
15. if(G.vexs[i] == v) return i;//找到
16. }
17. return -1;//不存在
18. }
19.
20. /************************************************************************/
21. /*
22.
23. */
24. /************************************************************************/
25. int FirstAdjVex(MGraph G,int v)
26. {
27. int i ;
28. for(i = 0; i<G.vexnum; i++)
29. if( G.arcs[v][i].adj ) return i;
30. if(i == (G.vexnum -1)) return -1;
31. return -1;
32.
33. }
34.
35. int NextAdjVex(MGraph G,int v,int w)
36. {
37. int i;
38. for( i = w+1; i<G.vexnum; i++)//+1
39. if(G.arcs[v][i].adj) return i;
40. if(i == (G.vexnum -1)) return -1;
41. return -1;
42.
43. }
44. /************************************************************************/
45. /*
46. 邻接矩阵的无向图的创建:
47. 注释的代码可以动态生成图。
48. */
49. /************************************************************************/
50.
51. void CreatUDG(MGraph &G){
52. "创建邻接矩阵的无向图:"<<endl;
53. int i,j,k,w;
54. //G5的存储:
55. G.arcnum = 8;
56. G.vexnum = 9;
57. for(i=0;i<G.vexnum;++i)
58. for(j=0;j<G.vexnum;++j) {
59. G.arcs[i][j].adj=0;
60. G.arcs[i][j].info=NULL;
61. }
62. '1';
63. '2';
64. '3';
65. '4';
66. '5';
67. '6';
68. '7';
69. '8';
70.
71. G.arcs[0][1].adj = 1;
72. G.arcs[0][1].info = NULL;
73. G.arcs[1][0].adj = 1;
74. G.arcs[1][0].info = NULL;
75.
76. G.arcs[1][3].adj = 1;
77. G.arcs[1][3].info = NULL;
78. G.arcs[3][1].adj = 1;
79. G.arcs[3][1].info = NULL;
80.
81. G.arcs[3][7].adj = 1;
82. G.arcs[3][7].info = NULL;
83. G.arcs[7][3].adj = 1;
84. G.arcs[7][3].info = NULL;
85.
86. G.arcs[7][4].adj = 1;
87. G.arcs[7][4].info = NULL;
88. G.arcs[4][7].adj = 1;
89. G.arcs[4][7].info = NULL;
90.
91. G.arcs[4][1].adj = 1;
92. G.arcs[4][1].info = NULL;
93. G.arcs[1][4].adj = 1;
94. G.arcs[1][4].info = NULL;
95.
96. G.arcs[0][2].adj = 1;
97. G.arcs[0][2].info = NULL;
98. G.arcs[2][0].adj = 1;
99. G.arcs[2][0].info = NULL;
100.
101. G.arcs[2][5].adj = 1;
102. G.arcs[2][5].info = NULL;
103. G.arcs[5][2].adj = 1;
104. G.arcs[5][2].info = NULL;
105.
106. G.arcs[5][6].adj = 1;
107. G.arcs[5][6].info = NULL;
108. G.arcs[6][5].adj = 1;
109. G.arcs[6][5].info = NULL;
110.
111. G.arcs[6][2].adj = 1;
112. G.arcs[6][2].info = NULL;
113. G.arcs[2][6].adj = 1;
114. G.arcs[2][6].info = NULL;
115. return ;
116. /*
117. char v1,v2;
118. cout<<"请输入无向图顶点个数和边数:"<<endl;
119. cin>>G.vexnum>>G.arcnum;
120. cout<<"请输入"<<G.vexnum<<"个顶点的值:"<<endl;
121. for(i=0;i<G.vexnum;++i) cin>>G.vexs[i];
122. for(i=0;i<G.vexnum;++i)
123. for(j=0;j<G.vexnum;++j) {
124. G.arcs[i][j].adj=0;
125. G.arcs[i][j].info=NULL;
126. }
127.
128. for( k=1;k<=G.arcnum;++k){
129. cout<<"请输入第"<<k<<"条边的两个顶点值和它们的权重:"<<endl;
130. cin>>v1>>v2>>w;
131. i = LocateVex(G,v1); j=LocateVex(G,v2);
132. G.arcs[i][j].adj=w;
133. G.arcs[j][i]=G.arcs[i][j];
134. }
135. */
136. }
137. /************************************************************************/
138. /* 有向图邻接矩阵的创建
139. */
140. /************************************************************************/
141. void CreatDG(MGraph &G){
142. int i,j,k,w;
143. char v1,v2;
144. G.arcnum = 8;
145. G.vexnum = 9;
146. "请输入有向图顶点个数和边数:";
147. cin>> G.vexnum>> G.arcnum;
148. "请输入"<<G.vexnum<<"个顶点的值:"<<endl;
149. for(i=0;i<G.vexnum;++i) cin>>G.vexs[i];
150. for(i=0;i<G.vexnum;++i)
151. for(j=0;j<G.vexnum;++j) {
152. G.arcs[i][j].adj = 0;
153. G.arcs[i][j].info = NULL;
154. }
155. for( k=1;k<=G.arcnum;++k){
156. "请输入第"<<k<<"条边的两个顶点值和它们的权重:"<<endl;
157. cin>>v1>>v2>>w;
158. i= LocateVex(G,v1); j = LocateVex(G,v2);
159. G.arcs[i][j].adj = w;
160. }
161. }
162.
163.
164. void visitVex(MGraph G, int v){
165. " ";
166. }
167.
168. /************************************************************************/
169. /* 以V为出发点对图G 进行递归地DFS 搜索
170. */
171. /************************************************************************/
172. void DFS(MGraph G,int v){
173. true;
174. //访问第v 个顶点
175. for(int w = FirstAdjVex(G,v); w>=0; w = NextAdjVex(G,v,w)){
176. if(!visited[w]) DFS(G,w); //w未访问过,递归DFS搜索
177.
178. }
179. }
180.
181. /************************************************************************/
182. /*
183. 无向图的深度遍历
184. */
185. /************************************************************************/
186. void DFSTraverse(MGraph G){//
187. int v;
188. for( v = 0; v < G.vexnum; ++v) visited[v] = false;
189. for( v = 0; v < G.vexnum; )
190. if(!visited[v]) DFS( G, v); //v未访问过,从vi开始DFS搜索
191. //不要像书上写的那样,++v放到for语句,这样会导致多出一次访问
192.
193. }
194.
195.
196. void printMGraph(MGraph G){
197. "邻接矩阵已经创建,邻接矩阵为:"<<endl;
198. for(int i=0;i<G.vexnum;i++){
199. for(int j=0;j<G.vexnum;j++)
200. " ";
201. cout<<endl;
202. }
203. }
204.
205.
206. void main(){
207.
208. MGraph G;
209.
210. CreatUDG(G);
211. printMGraph(G);
212. "无向图邻接矩阵的深度遍历结果:"<<endl;
213. DFSTraverse(G);
214. }
2) 邻接表的表示实现方式
1. // stdafx.h : include file for standard system include files,
2. // or project specific include files that are used frequently, but
3. // are changed infrequently
4. //
5.
6. #pragma once
7.
8. #include "targetver.h"
9. #include <stdio.h>
10. #include "stdlib.h"
11. #include <iostream>
12. using namespace std;
13.
14. //宏定义
15. #define TRUE 1
16. #define FALSE 0
17. #define NULL 0
18. #define OK 1
19. #define ERROR 0
20. #define INFEASIBLE -1
21. #define OVERFLOW -2
22.
23. #define INFINITY INT_MAX
24. #define MAX_VERTEX_NUM 30
25.
26.
27. typedef int Status ;
28. typedef int ElemType ;
29. typedef int VrType ;
30. typedef char VertexType ;
31.
32. /************************************************************************/
33. /* 邻接表示的图数据结构
34. */
35. /************************************************************************/
36. //定义边结点,即表节点
37. typedef struct ArcNode
38. {
39. int adjvex; //弧所指的顶点位置
40. //指向下一条弧的指针
41. }ArcNode;
42.
43. //定义顶点节点,即头节点
44. typedef struct VNode
45. {
46. //顶点信息
47. //指向第一条依附该顶点的弧的指针
48. }VNode,AdjList[MAX_VERTEX_NUM];
49.
50. //定义无向图
51. typedef struct
52. {
53. AdjList vertices;
54. int vexnum,arcnum; //图的当前顶点数和弧数
55. }ALGraph;
1. // Test.cpp : Defines the entry point for the console application.
2. //
3. #include "stdafx.h"
4.
5. bool visited[MAX_VERTEX_NUM]; //访问标识
6. Status (*VisitFunc) (int v); //函数变量
7.
8.
9. /************************************************************************/
10. /* 在无向图中添加以m,n为顶点的边
11. */
12. /************************************************************************/
13. void ArcAdd(ALGraph &G,int m,int n){
14.
15. ArcNode *p,*h,*q;
16. new ArcNode;
17. p->adjvex = m;
18. p->nextarc = NULL;
19. h = q = G.vertices[n].firstarc;
20. if(q == NULL)
21. G.vertices[n].firstarc = p;
22. else {
23. if((p->adjvex)>(q->adjvex)){
24. p->nextarc = q;
25. G.vertices[n].firstarc = p;
26. }
27. else {
28. while( G.vertices[n].firstarc != NULL && q->nextarc != NULL && (p->adjvex)<(q->adjvex)){ //使邻接表中边的数据按大到小排列。
29. h = q;
30. q = q->nextarc;
31. }
32. if(q->nextarc == NULL&&(p->adjvex)<(q->adjvex)){
33. q->nextarc = p;
34. }
35. else {
36. p->nextarc = q;
37. h->nextarc = p;
38. }
39. }
40. }
41. }
42. /************************************************************************/
43. /*
44. 创建无向图
45. */
46. /************************************************************************/
47. void CreateDG(ALGraph &G){
48. "请输入顶点个数和边数:"<<endl;
49. cin>> G.vexnum>> G.arcnum;
50. "请输入顶点值:"<<endl;
51. for(int i= 1; i<= G.vexnum; i++) {
52. char t;
53. cin>>t;
54. G.vertices[i].data = t;
55. G.vertices[i].firstarc = NULL;
56. }
57. int m, n;
58. for(int k = 1; k<=G.arcnum; k++){
59. "请输入第"<<k<<"条边的两个顶点:"<<endl;
60. cin>>m>>n;
61. if(m<= G.vexnum && n <= G.vexnum && m>0 && n>0){
62. ArcAdd(G, m, n);
63. ArcAdd(G, n, m);
64. }
65. else cout<<"ERROR."<<endl;
66. }
67. }
68. /************************************************************************/
69. /* 打印邻接表的无向图
70. */
71. /************************************************************************/
72. void PrintGraph(ALGraph G)
73. {
74. "无向图的创建完成,该图的邻接表表示为:"<<endl;
75. ArcNode *p;
76. for(int i=1; i<=G.vexnum; i++)
77. {
78. if(G.vertices[i].firstarc == NULL)
79. "-->NULL"<<endl;
80. else
81. {
82. p = G.vertices[i].firstarc;
83. "-->";
84. while(p->nextarc!=NULL)
85. {
86. "-->";
87. p = p->nextarc;
88. }
89. "-->NULL"<<endl;
90. }
91. }
92. }
93.
94.
95. /************************************************************************/
96. /* 返回v的第一个邻接顶点。若顶点在G中没有邻接表顶点,则返回“空”。
97. */
98. /************************************************************************/
99. int FirstAdjVex(ALGraph G,int v)
100. {
101. if(G.vertices[v].firstarc)
102. return G.vertices[v].firstarc->adjvex;
103. else
104. return NULL;
105. }
106. /************************************************************************/
107. /*
108. 返回v的(相对于w的)下一个邻接顶点。若w是v的最后一个邻接点,则返回“回”。
109. */
110. /************************************************************************/
111. int NextAdjVex(ALGraph G,int v,int w)
112. {
113. ArcNode *p;
114. if(G.vertices[v].firstarc==NULL)
115. return NULL;
116. else {
117. p = G.vertices[v].firstarc;
118. while(p->adjvex!=w) p = p->nextarc;
119.
120. if(p->nextarc == NULL) return NULL;
121. else return p->nextarc->adjvex;
122. }
123. }
124.
125.
126.
127. void visitVex(ALGraph G, int v){
128. " ";
129. }
130.
131. /************************************************************************/
132. /*
133. 无向图的深度遍历
134. */
135. /************************************************************************/
136. //从第v个顶点出发递归地深度优先遍历图G
137. void DFS(ALGraph G,int v)
138. {
139. true;
140. visitVex(G, v);
141. for(int w = FirstAdjVex(G,v);w >= 1; w = NextAdjVex(G,v,w))
142. if(!visited[w]) DFS(G,w);
143. }
144. //对图G作深度优先遍历
145. void DFSTraverse(ALGraph G)
146. {
147. for(int v = 1; v <= G.vexnum; v++) visited[v]=false;
148. for(int m = 1; m <= G.vexnum; m++)
149. if(!visited[m]) DFS(G,m);
150. }
151.
152. void main(){
153. ALGraph G;
154. CreateDG(G);
155. PrintGraph(G);
156. DFSTraverse(G);
157. }
分析上述算法,在遍历时,对图中每个顶点至多调用一次DFS 函数,因为一旦某个顶点被标志成已被访问,就不再从它出发进行搜索。因此,遍历图的过程实质上是对每个顶点查找其邻接点的过程。其耗费的时间则取决于所采用的存储结构。当用二维数组表示邻接矩阵图的存储结构时,查找每个顶点的邻接点所需时间为O(n2) ,其中n 为图中顶点数。而当以邻接表作图的存储结构时,找邻接点所需时间为O(e),其中e 为无向图中边的数或有向图中弧的数。由此,当以邻接表作存储结构时,深度优先搜索遍历图的时间复杂度为O(n+e) 。
2.广度优先搜索
广度优先搜索(Breadth_First Search) 遍历类似于树的按层次遍历的过程。
假设从图中某顶点v 出发,在访问了v 之后依次访问v 的各个未曾访问过和邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。换句话说,广度优先搜索遍历图的过程中以v 为起始点,由近至远,依次访问和v 有路径相通且路径长度为1,2,…的顶点。
对图如下图所示无向图G5 进行广度优先搜索遍历:
广度搜索过程:
首先访问v1 和v1 的邻接点v2 和v3,然后依次访问v2 的邻接点v4 和v5 及v3 的邻接点v6 和v7,最后访问v4 的邻接点v8。由于这些顶点的邻接点均已被访问,并且图中所有顶点都被访问,由些完成了图的遍历。得到的顶点访问序列为:
v1→v2 →v3 →v4→ v5→ v6→ v7 →v8
和深度优先搜索类似,在遍历的过程中也需要一个访问标志数组。并且,为了顺次访问路径长度为2、3、…的顶点,需附设队列以存储已被访问的路径长度为1、2、… 的顶点。
实现:
1. // stdafx.h : include file for standard system include files,
2. // or project specific include files that are used frequently, but
3. // are changed infrequently
4. //
5.
6. #pragma once
7.
8. #include <stdio.h>
9. #include "stdlib.h"
1. // func.h :
2. #pragma once
3.
4. #include <iostream>
5. using namespace std;
6.
7. //宏定义
8. #define TRUE 1
9. #define FALSE 0
10. #define NULL 0
11. #define OK 1
12. #define ERROR 0
13. #define INFEASIBLE -1
14. #define OVERFLOW -2
15.
16. #define INFINITY INT_MAX
17. #define MAX_VERTEX_NUM 30
18.
19.
20. typedef int Status ;
21. typedef int ElemType ;
22. typedef int VrType ;
23. typedef char VertexType ;
24.
25. /************************************************************************/
26. /* 邻接表示的图数据结构
27. */
28. /************************************************************************/
29. //定义边结点
30. typedef struct ArcNode
31. {
32. int adjvex; //弧所指的顶点位置
33. //指向下一条弧的指针
34. }ArcNode;
35.
36. //定义顶点结点
37. typedef struct VNode
38. {
39. //顶点信息
40. //指向第一条依附该顶点的弧的指针
41. }VNode,AdjList[MAX_VERTEX_NUM];
42.
43. //定义无向图
44. typedef struct
45. {
46. AdjList vertices;
47. int vexnum,arcnum; //图的当前顶点数和弧数
48. }ALGraph;
49.
50.
51. /************************************************************************/
52. /* 需要 */
53. /************************************************************************/
54. typedef struct node //定义结点
55. {
56. char data;
57. node *next;
58. }*Link;
59.
60. typedef struct //定义链表
61. {
62. Link head,tail;
63. int len;
64. }Queue;
65.
66. /************************************************************************/
67. /* 构造一个带头结点和尾结点的空的线性链表队列Q
68. */
69. /************************************************************************/
70. Status InitQueue(Queue &Q)
71. {
72. new node;
73. new node;
74. Q.tail->next = NULL;
75. Q.len = 0;
76. return 0;
77. }
78.
79. /************************************************************************/
80. /*
81. //在线性链表的队列L的结尾添加一个结点
82. */
83. /************************************************************************/
84. void EnQueue(Queue &Q,int e)
85. {
86. new node;
87. Q.tail->next = q;
88. Q.tail->data = e;
89. Q.tail = q;
90. Q.tail->next = NULL;
91. Q.len++;
92. }
93. /************************************************************************/
94. /* 出列,并将出列的元素值用e返回
95. */
96. /************************************************************************/
97. void DeleteQueue(Queue &Q,int &e)
98. {
99. if(Q.head->next == Q.tail) {
100. "队列为空"<<endl;
101. e = NULL;
102. else {
103. Link p,q;
104. p = Q.head->next;
105. q = p->next;
106. Q.head->next = q;
107. e = p->data;
108. delete p;
109. Q.len--;
110. }
111. }
1. // Test.cpp : Defines the entry point for the console application.
2. //
3. #include "stdafx.h"
4. #include "func.h"
5. bool visited[MAX_VERTEX_NUM]; //访问标识
6. Status (*VisitFunc) (int v); //函数变量
7.
8. /************************************************************************/
9. /* 在无向图中添加以m,n为顶点的边
10. */
11. /************************************************************************/
12. void ArcAdd(ALGraph &G,int m,int n){
13.
14. ArcNode *p,*h,*q;
15. new ArcNode;
16. p->adjvex = m;
17. p->nextarc = NULL;
18. h = q = G.vertices[n].firstarc;
19. if(q == NULL)
20. G.vertices[n].firstarc = p;
21. else {
22. if((p->adjvex)>(q->adjvex)){
23. p->nextarc = q;
24. G.vertices[n].firstarc = p;
25. }
26. else {
27. while( G.vertices[n].firstarc != NULL && q->nextarc != NULL && (p->adjvex)<(q->adjvex)){
28. //使邻接表中边的数据按大到小排列。
29. h = q;
30. q = q->nextarc;
31. }
32. if(q->nextarc == NULL&&(p->adjvex)<(q->adjvex)){
33. q->nextarc = p;
34. }
35. else {
36. p->nextarc = q;
37. h->nextarc = p;
38. }
39. }
40. }
41. }
42. /************************************************************************/
43. /*
44. 创建无向图
45. */
46. /************************************************************************/
47. void CreateDG(ALGraph &G){
48. "请输入顶点个数和边数:"<<endl;
49. cin>> G.vexnum>> G.arcnum;
50. "请输入顶点值:"<<endl;
51. for(int i= 1; i<= G.vexnum; i++) {
52. char t;
53. cin>>t;
54. G.vertices[i].data = t;
55. G.vertices[i].firstarc = NULL;
56. }
57. int m, n;
58. for(int k = 1; k<=G.arcnum; k++){
59. "请输入第"<<k<<"条边的两个顶点:"<<endl;
60. cin>>m>>n;
61. if(m<= G.vexnum && n <= G.vexnum && m>0 && n>0){
62. ArcAdd(G, m, n);
63. ArcAdd(G, n, m);
64. }
65. else cout<<"ERROR."<<endl;
66. }
67. }
68.
69. /************************************************************************/
70. /* 打印邻接表的无向图
71. */
72. /************************************************************************/
73. void PrintGraph(ALGraph G)
74. {
75. "无向图的创建完成,该图的邻接表表示为:"<<endl;
76. ArcNode *p;
77. for(int i=1; i<=G.vexnum; i++)
78. {
79. if(G.vertices[i].firstarc == NULL)
80. "-->NULL"<<endl;
81. else
82. {
83. p = G.vertices[i].firstarc;
84. "-->";
85. while(p->nextarc!=NULL)
86. {
87. "-->";
88. p = p->nextarc;
89. }
90. "-->NULL"<<endl;
91. }
92. }
93. }
94.
95. /************************************************************************/
96. /* 返回v的第一个邻接顶点。若顶点在G中没有邻接表顶点,则返回“空”。
97. */
98. /************************************************************************/
99. int FirstAdjVex(ALGraph G,int v)
100. {
101. if(G.vertices[v].firstarc)
102. return G.vertices[v].firstarc->adjvex;
103. else
104. return NULL;
105. }
106. /************************************************************************/
107. /*
108. 返回v的(相对于w的)下一个邻接顶点。若w是v的最后一个邻接点,则返回“回”。
109. */
110. /************************************************************************/
111. int NextAdjVex(ALGraph G,int v,int w)
112. {
113. ArcNode *p;
114. if(G.vertices[v].firstarc==NULL)
115. return NULL;
116. else {
117. p = G.vertices[v].firstarc;
118. while(p->adjvex!=w) p = p->nextarc;
119.
120. if(p->nextarc == NULL) return NULL;
121. else return p->nextarc->adjvex;
122. }
123. }
124.
125. void visitVex(ALGraph G, int v){
126. " ";
127. }
128.
129. /************************************************************************/
130. /*
131. 广度优先遍历图G
132. */
133. /************************************************************************/
134.
135. void BFSTraverse(ALGraph G)
136. {
137. Queue Q;
138. int u;
139. for(int m=1; m<= G.vexnum; m++) visited[m] = false;
140. //借助辅助队列。
141. for(int v=1;v<=G.vexnum;v++)
142. if(!visited[v]) {
143. true;
144. visitVex(G,v);
145. EnQueue(Q,v);
146. while(Q.len!=0)
147. {
148. DeleteQueue(Q,u);
149. for(int w=FirstAdjVex(G,u);w>=1;w=NextAdjVex(G,u,w))
150. if(!visited[w])
151. {
152. true;
153. visitVex(G,v);
154. EnQueue(Q,w);
155. }
156. }
157. }
158. cout<<endl;
159. }
160.
161. void main(){
162. ALGraph G;
163. CreateDG(G);
164. PrintGraph(G);
165. "广度优先搜索的结果为:"<<endl;
166. BFSTraverse(G);
167. }
分析上述算法,每个顶点至多进一次队列。遍历图的过程实质是通过边或弧找邻接点的过程,因此广度优先搜索遍历图的时间复杂度和深度优先搜索遍历相同,两者不同之处仅仅在于对顶点访问的顺序不同。