1.深度优先搜索(简称“深搜”或DFS)
深度优先搜索的过程类似于树的先序遍历,首先从例子中体会深度优先搜索。


采用深度优先算法遍历上图的过程为:
1.首先任意找一个未被遍历过的顶点,例如从A开始,由于A率先访问过了,所以,需要标记A的状态为访问过;
2.然后遍历A的邻接点,例如访问B,并做标记,然后访问B的邻接点,例如C (做标记),然后D,然后F......
3.当继续遍历H的邻接点时,根据之前做的标记显示,所有邻接点都被访问过了。此时,从H回退到G,看G是否有未被访问过的邻接点,如果没有,继续回退到F, E,D......
4.回退到D时,找到未被访问的I, 继续查看I的临界点是否有未被访问的;
最后深度优先搜索获得的顶点的遍历次序为:
A -> B -> C -> D -> E -> F -> G -> H -> I
所谓深度优先搜索,是从图中的一个顶点出发,每次遍历当前访问顶点的临界点,一直到访问的顶点没有未被访问过的临界点为止。然后采用依次回退的方式,查看来的路上每一个顶点是否有其它未被访问的临界点。访问完成后,判断图中的顶点是否已经全部遍历完成,如果没有,以未访问的顶点为起始点,重复上述过程。
1.1邻接矩阵的深度优先遍历
- 将图的顶点和边信息输入到图结构中;
- 创建⼀个visited 数组,⽤来标识顶点是否已经被遍历过.
- 初始化visited 数组,将数组中元素置为FALSE
- 选择顶点开始遍历.(注意非连通图的情况)
- 进⼊递归; 打印i 对应的顶点信息. 并将该顶点标识为已遍历.
- 循环遍历边表,判断当前arc[i][j] 是否等于1,并且当前该顶点没有被遍历过,则继续递归 DFS;
Boolean visited[MAXVEX]; /* 访问标志的数组 */
void DFS(MGraph G, int i){
//3.顶点i置为已访问 并打印
visited[i] = TRUE;
printf("%c", G.vexs[i]);
//4.循环遍历边表
for (int j=0; j<G.numVertexes; j++) {
//判断arc[i][j]是否等于1 并且该顶点没有被访问过 继续递归遍历
if (G.arc[i][j] == 1 && !visited[j]) {
DFS(G, j);
}
}
}
void DFSTravese(MGraph G){
//1.初始化visited数组
for (int i = 0; i<G.numVertexes; i++) {
visited[i] = FALSE;
}
//2.选择顶点开始遍历
for (int i=0; i<G.numVertexes; i++) {
if (!visited[i]) {
DFS(G, i);
}
}
}
1.2邻接表的深度优先遍历
- 利利⽤用邻接矩阵将信息存储到邻接表中
- 创建⼀一个visited 数组,⽤用来标识顶点是否已经被遍历过.
- 初始化visited 数组,将数组中元素置为FALSE
- 选择顶点开始遍历.(注意⾮非连通图的情况)
- 进⼊入递归; 打印i 对应的顶点信息. 并将该顶点标识为已遍历.
- 循环遍历边表,判断当前顶点 是否等于1,并且当前该顶点没有被遍历过,则继续递归 DFS;
//1.创建⼀个visited 数组,⽤来标识顶点是否已经被遍历过.
Boolean visited[MAXSIZE];
/* 邻接表的深度优先递归算法 */
void DFS(GraphAdjList GL, int i){
EdgeNode *p;
//4.打印i顶点的信息 并将改顶点标记为已遍历
printf("%c ", GL->adjList[i].data);
visited[i] = TRUE;
p = GL->adjList[i].firstedge;
while (p) {
if (!visited[p->adjvex]) {
DFS(GL, p->adjvex);
}
p = p->next;
}
}
/* 邻接表的深度遍历操作 */
void DFSTraverse(GraphAdjList GL){
for (int i=0; i<GL->numVertexes; i++) {
//2. 将访问记录数组默认置为FALSE
visited[i] = FALSE;
}
//3. 选择一个顶点开始DFS遍历.
for (int i=0; i<GL->numVertexes; i++) {
if (!visited[i]) {
DFS(GL, i);
}
}
}
2.广度优先搜索(BFS)
广度优先搜索类似于树的层次遍历。从图中的某一顶点出发,遍历每一个顶点时,依次遍历其所有的邻接点,然后再从这些邻接点出发,同样依次访问它们的邻接点。按照此过程,直到图中所有被访问过的顶点的邻接点都被访问到。
最后还需要做的操作就是查看图中是否存在尚未被访问的顶点,若有,则以该顶点为起始点,重复上述遍历的过程。
广度优先搜索的实现需要借助队列这一特殊数据结构.

2.将A出栈,A未被标记的邻接点BF(并标记)入栈
3.B出栈,B的未被标记的邻接点IG(并标记)入栈
4.F出栈,邻接点E入栈
5.C出栈,D入栈
6.I出栈,I没有未被标记的邻接点
7.G出栈,H入栈
8.E出栈
9.D出栈
10.H出栈,此时已全部标记完成。
遍历顶点的顺序为:
A -> B -> F -> C -> I -> G -> E -> D -> H
2.1 邻接矩阵的广度优先遍历
/*邻接矩阵广度优先遍历-代码实现*/
//访问标志数组
Boolean visited[MAXSIZE];
void BFSTraverse(MGraph G){
//初始化队列
Queue Q;
InitQueue(&Q);
//将访问记录数组默认置为FALSE
for (int i=0; i<G.numVertexes; i++) {
visited[i] = FALSE;
}
//遍历邻接表中的每一个顶点(对于连通图只会执行1次,这个循环是针对非连通图)
for (int i=0; i<G.numVertexes; i++) {
if (!visited[i]) {
visited[i] = TRUE;
printf("%c ",G.vexs[i]);
//下标入队
EnQueue(&Q, i);
int k;
while (!QueueEmpty(Q)) {
DeQueue(&Q, &k);
for (int j=0; j<G.numVertexes; j++) {
if (G.arc[k][j] == 1 && !visited[j]) {
visited[j] = TRUE;
printf("%c ",G.vexs[j]);
EnQueue(&Q, j);
}
}
}
}
}
}
2.2 邻接表的广度优先遍历
/*邻接表广度优先遍历*/
Boolean visited[MAXSIZE]; /* 访问标志的数组 */
void BFSTraverse(GraphAdjList GL){
EdgeNode *p;
Queue Q;
InitQueue(&Q);
for (int i=0; i<GL->numVertexes; i++) {
visited[i] = FALSE;
}
int k;
for (int i=0; i<GL->numVertexes; i++) {
if (!visited[i]) {
EnQueue(&Q, i);
visited[i] = TRUE;
printf("%c ",GL->adjList[i].data);
while (!QueueEmpty(Q)) {
DeQueue(&Q, &k);
p = GL->adjList[k].firstedge;
while (p) {
if (!visited[p->adjvex]) {
EnQueue(&Q, p->adjvex);
visited[p->adjvex] = TRUE;
printf("%c ",GL->adjList[p->adjvex].data);
}
p = p->next;
}
}
}
}
}